import * as crypto from 'crypto-js';
import { formatISO } from 'date-fns';
import { ConfigStore } from "fastly:config-store";
const MS_API_VERSION = "2017-11-09";
addEventListener('fetch', event => event.respondWith(handleRequest(event)));
async function handleRequest(event) {
let req = fixupURL(event.request);
if (req.method === "GET" || req.method === "HEAD") {
authorizeRequest(req);
let res = await fetch(req, {
backend: "azure_backend",
});
res.headers.delete("x-ms-request-id");
res.headers.delete("x-ms-blob-type");
res.headers.delete("x-ms-server-encrypted");
res.headers.delete("x-ms-version");
res.headers.delete("x-ms-creation-time");
res.headers.delete("x-ms-lease-status");
res.headers.delete("x-ms-lease-state");
res.headers.delete("content-md5");
res.headers.delete("server");
return res;
} else if (req.method === "PURGE") {
req.headers.set("host", getConfig().HOST);
return await fetch(req, {
backend: "azure_backend",
});
} else {
return new Response("This method is not allowed", { status: 405 });
}
}
function authorizeRequest(req) {
const cfg = getConfig();
const timestamp = new Date().toUTCString();
const decodedKey = crypto.enc.Base64.parse(cfg.ACCOUNT_KEY);
const canonicalizedHeaders = `x-ms-date:${timestamp}\nx-ms-version:${MS_API_VERSION}\n`;
const url = new URL(req.url);
const canonicalizedResource = `/${cfg.ACCOUNT_NAME}${url.pathname}`;
console.log(`canonicalizedResource = ${canonicalizedResource}`);
const stringToSign = `GET\n\n\n\n${canonicalizedHeaders}${canonicalizedResource}`;
const signature_binary = hmacSha256(decodedKey, stringToSign);
const signature = crypto.enc.Base64.stringify(signature_binary);
const authorization = `SharedKeyLite ${cfg.ACCOUNT_NAME}:${signature}`;
req.headers.set("host", cfg.HOST);
req.headers.set("authorization", authorization);
req.headers.set("x-ms-date", timestamp);
req.headers.set("x-ms-version", MS_API_VERSION);
console.log(`Path: ${url.pathname}, Authorization: ${authorization}`);
}
function fixupURL(req) {
let url = new URL(req.url);
url.search = "";
url.pathname = `/${getConfig().BLOB_CONTAINER_NAME}${url.pathname}`;
return new Request(url, req);
}
function hmacSha256(signingKey, stringToSign) {
return crypto.HmacSHA256(stringToSign, signingKey, { asBytes: true });
}
function getConfig() {
const config = new ConfigStore('azure_config');
return {
ACCOUNT_NAME: config.get("account_name"),
ACCOUNT_KEY: config.get("account_key"),
HOST: `${config.get("account_name")}.blob.core.windows.net`,
BLOB_CONTAINER_NAME: config.get("blob_container_name")
};
}