Last active
October 4, 2023 02:46
-
-
Save kyouheicf/46e46ac1de2a2ccf61c0e329de22c0c5 to your computer and use it in GitHub Desktop.
Cloudflare Snippets (alpha) を使う - Qiita https://qiita.com/khayama/items/e33fbfebab4907f5d5b7
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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