function arrBufToB64Url(buf: ArrayBuffer) { const b64data = btoa(String.fromCharCode(...new Uint8Array(buf))); return b64data.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_"); } function stringToBuffer(str: string) { const buffer = new ArrayBuffer(str.length); const ui8 = new Uint8Array(buffer); for (let i = 0, bufLen = str.length; i < bufLen; i++) { ui8[i] = str.charCodeAt(i); } return buffer; } export async function GenerateUploadURL( env: Env, path: string, size: number, fileExt: string ): Promise { const accessToken = await GetAccessToken(env); const contentTypes: { [k: string]: string } = { gif: "image/gif", heic: "image/heic", heif: "image/heif", jfif: "image/jpeg", jpeg: "image/jpeg", jpg: "image/jpeg", m4v: "video/x-m4v", mkv: "video/x-matroska", mov: "video/quicktime", mp4: "video/mp4", png: "image/png", webp: "image/webp", webm: "video/webm", wmv: "video/x-ms-wmv", }; const resumableUploadReq = await fetch( `https://storage.googleapis.com/upload/storage/v1/b/portal-carcrushers-cc/o?uploadType=resumable&name=${encodeURIComponent( path )}`, { headers: { authorization: `Bearer ${accessToken}`, "x-upload-content-type": contentTypes[fileExt], "x-upload-content-length": size.toString(), }, method: "POST", } ); if (!resumableUploadReq.ok) throw new Error( `Failed to create resumable upload: ${await resumableUploadReq.text()}` ); const url = resumableUploadReq.headers.get("location"); if (!url) throw new Error("No location header returned"); return url; } async function GetAccessToken(env: Env): Promise { const claimSet = btoa( JSON.stringify({ aud: "https://oauth2.googleapis.com/token", exp: Math.floor(Date.now() / 1000) + 120, iat: Math.floor(Date.now() / 1000), iss: env.WORKER_GSERVICEACCOUNT, scope: "https://www.googleapis.com/auth/datastore https://www.googleapis.com/auth/devstorage.read_write", }) ) .replaceAll("+", "-") .replaceAll("/", "_") .replaceAll("=", ""); const signingKey = await crypto.subtle.importKey( "pkcs8", stringToBuffer( atob(env.STORAGE_ACCOUNT_KEY.replace(/(\r\n|\n|\r)/gm, "")) ), { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, false, ["sign"] ); const signature = await crypto.subtle.sign( { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, signingKey, stringToBuffer(`eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.${claimSet}`) ); const assertion = `eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.${claimSet}.${arrBufToB64Url( signature )}`; const tokenRequest = await fetch("https://oauth2.googleapis.com/token", { body: `grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=${assertion}`, headers: { "content-type": "application/x-www-form-urlencoded", }, method: "POST", }); if (!tokenRequest.ok) throw new Error(`Failed to get access token: ${await tokenRequest.text()}`); return ((await tokenRequest.json()) as { [k: string]: any }).access_token; }