Skip to content

Instantly share code, notes, and snippets.

@kyouheicf
Last active October 4, 2023 02:46
Show Gist options
  • Save kyouheicf/46e46ac1de2a2ccf61c0e329de22c0c5 to your computer and use it in GitHub Desktop.
Save kyouheicf/46e46ac1de2a2ccf61c0e329de22c0c5 to your computer and use it in GitHub Desktop.
Cloudflare Snippets (alpha) を使う - Qiita https://qiita.com/khayama/items/e33fbfebab4907f5d5b7
/*
Replace these parameter with yours
- bucket name : YOUR_GCS_BUCKET_NAME
- bucket location : asia-northeast1
- accessKeyId : YOUR_GCS_ACCESS_KEY_ID
- secretAccessKey : YOUR_GCS_SECRET_ACCESS_KEY
*/
export default {
async fetch(request, env, ctx) {
const textToBin = (text) =>
new TextEncoder().encode(text);
const binToHexText = (buf) =>
[...buf].map((b) => b.toString(16).padStart(2, "0")).join("");
const digestSha256 = async (data) =>
new Uint8Array(await crypto.subtle.digest("SHA-256", data));
const hmacSha256 = async (key, message) => {
const cryptoKey = await crypto.subtle.importKey("raw", key, { name: "HMAC", hash: "SHA-256" }, true, ["sign"]);
const signedData = await crypto.subtle.sign("HMAC", cryptoKey, message);
return new Uint8Array(signedData);
};
const signRequest = async (request) => {
const dateTimeText = new Date().toISOString().replace(/\.[0-9]{3}/, "").replace(/[-:]/g, "");
//console.log(`dateTimeText === ${dateTimeText}`)
const dateText = dateTimeText.substring(0, 8);
//console.log(`dateText === ${dateText}`)
const requrl = new URL(request.url);
const pathname = requrl.pathname;
const hostname = `YOUR_GCS_BUCKET_NAME.storage.googleapis.com`
const url = `https://${hostname}${pathname}`
//console.log(`url === ${url}`)
const emptyHash = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';
const signedHeaders = new Headers({ Host: hostname, "X-Amz-Content-Sha256": emptyHash, "X-Amz-Date": dateTimeText });
//console.log(`signedHeaders === ${JSON.stringify([...signedHeaders])}`);
const signedHeadersText = Array.from(signedHeaders.entries())
.map(([key]) => key.toLowerCase())
.sort()
.join(";");
//console.log(`signedHeadersText === ${signedHeadersText}`)
const canonicalQueryString = Array.from(requrl.searchParams.entries())
.map(([key, val]) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`)
.sort()
.join("&");
//console.log(`canonicalQueryString === ${canonicalQueryString}`)
const canonicalHeaders = Array.from(signedHeaders.entries())
.map(([key, val]) => `${key.toLowerCase().trim().replace(/ +/g, " ")}:${val.trim().replace(/ +/g, " ")}\n`)
.sort()
.join("");
//console.log(`canonicalHeaders === ${canonicalHeaders}`)
const hashedPayload = binToHexText(await digestSha256(new Uint8Array(await request.clone().arrayBuffer())));
//console.log(`hashedPayload === ${hashedPayload}`)
const canonicalRequest = [
request.method,
pathname,
canonicalQueryString,
canonicalHeaders,
signedHeadersText,
hashedPayload,
].join("\n");
//console.log(`canonicalRequest === ${canonicalRequest}`)
const hashedCanonicalRequest = binToHexText(await digestSha256(textToBin(canonicalRequest)));
//console.log(`hashedCanonicalRequest === ${hashedCanonicalRequest}`)
const stringToSign = [
"AWS4-HMAC-SHA256",
dateTimeText,
`${dateText}/asia-northeast1/s3/aws4_request`,
hashedCanonicalRequest,
].join("\n");
//console.log(`stringToSign === ${stringToSign}`)
const accessKeyId = "YOUR_GCS_ACCESS_KEY_ID"
const secretAccessKey = "YOUR_GCS_SECRET_ACCESS_KEY"
const kDate = await hmacSha256(textToBin(`AWS4${secretAccessKey}`), textToBin(dateText));
//console.log(`kDate === ${kDate}`)
const kRegion = await hmacSha256(kDate, textToBin("asia-northeast1"));
//console.log(`kRegion === ${kRegion}`)
const kService = await hmacSha256(kRegion, textToBin("s3"));
//console.log(`kService === ${kService}`)
const kSigning = await hmacSha256(kService, textToBin("aws4_request"));
//console.log(`kSigning === ${kSigning}`)
const signature = binToHexText(await hmacSha256(kSigning, textToBin(stringToSign)));
//console.log(`signature === ${signature}`)
const signedRequest = new Request(url, {
method: request.method,
headers: request.headers,
});
signedHeaders.forEach((value, name) => signedRequest.headers.set(name, value));
const credential = [accessKeyId, dateText, "asia-northeast1", "s3", "aws4_request"].join("/");
const authorization = `AWS4-HMAC-SHA256 Credential=${credential}, SignedHeaders=${signedHeadersText}, Signature=${signature}`;
signedRequest.headers.set("Authorization", authorization);
//console.log(`signedRequest.headers === ${JSON.stringify([...signedRequest.headers])}`);
return signedRequest;
}
const signedRequest = await signRequest(request);
let response = await fetch(signedRequest)
response = new Response(response.body, response);
response.headers.append("x-snippets-hello", "Hello from Cloudflare Snippets");
return response;
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment