I'm trying to migrate my CORS checker app from heroku to cloudflare workers as it seems to be a perfect fit for my use case.
The heroku app uses axios to asks a website for an options call to see if there are any headers with x-frame-options. If so, I check if it's denied, and return this as a boolean value in the REST response.
This sounds really simple, but I'm having trouble making it work on cloudflare workers. Am I correct in assuming that cloudflare is stripping these headers and there is no way to get this working with cloudflare workers?
Here is the full worker code
// node_modules/itty-router/dist/itty-router.mjs
var e = ({ base: e2 = "", routes: r = [] } = {}) => ({ __proto__: new Proxy({}, { get: (a, o, t) => (a2, ...p) => r.push([o.toUpperCase(), RegExp(`^${(e2 + a2).replace(/(\/?)\*/g, "($1.*)?").replace(/(\/$)|((?<=\/)\/)/, "").replace(/(:(\w+)\+)/, "(?<$2>.*)").replace(/:(\w+)(\?)?(\.)?/g, "$2(?<$1>[^/]+)$2$3").replace(/\.(?=[\w(])/, "\\.").replace(/\)\.\?\(([^\[]+)\[\^/g, "?)\\.?($1(?<=\\.)[^\\.")}/*$`), p]) && t }), routes: r, async handle(e3, ...a) {
let o, t, p = new URL(e3.url), l = e3.query = {};
for (let [e4, r2] of p.searchParams)
l[e4] = void 0 === l[e4] ? r2 : [l[e4], r2].flat();
for (let [l2, s, c] of r)
if ((l2 === e3.method || "ALL" === l2) && (t = p.pathname.match(s))) {
e3.params = t.groups || {};
for (let r2 of c)
if (void 0 !== (o = await r2(e3.proxy || e3, ...a)))
return o;
}
} });
// src/index.ts
var router = e();
var corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,HEAD,POST,OPTIONS",
"Access-Control-Max-Age": "86400"
};
function jsonResponse(body) {
return new Response(JSON.stringify(body), {
status: 200,
headers: {
"Content-Type": "application/json",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload"
}
});
}
function handleOptions(request) {
let headers = request.headers;
if (headers.get("Origin") !== null && headers.get("Access-Control-Request-Method") !== null && headers.get("Access-Control-Request-Headers") !== null) {
let respHeaders = {
...corsHeaders,
"Access-Control-Allow-Headers": request.headers.get("Access-Control-Request-Headers")
};
return new Response(null, {
headers: respHeaders
});
} else {
return new Response(null, {
headers: {
Allow: "GET, HEAD, POST, OPTIONS"
}
});
}
}
router.options("/test-cors", async function(request) {
return handleOptions(request);
});
router.post("/test-cors", async function(request) {
const url = request.body.url;
const externalRequest = new Request(url, { method: "head" });
try {
let response = await fetch(externalRequest);
if (response.headers.get("x-frame-options") !== null) {
const frameOptionsValue = response.headers.get("x-frame-options");
if (frameOptionsValue === "SAMEORIGIN") {
return jsonResponse({ canAccess: false });
} else {
return jsonResponse({ canAccess: true });
}
} else {
return jsonResponse({ canAccess: true });
}
} catch (error) {
console.error(error);
if (error.code === "ENOTFOUND" || error.response.status === 404) {
return jsonResponse({ canAccess: false, reason: "NOT_FOUND" });
} else {
return jsonResponse({ canAccess: false });
}
}
});
router.all("*", (request, args) => {
return new Response("Not Found", {
status: 404,
headers: {
"Content-Type": "text/html; charset=utf-8",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload"
}
});
});
var src_default = {
async fetch(request, env, ctx) {
return router.handle(request);
}
};
export {
src_default as default
};
//# sourceMappingURL=index.js.map
So I've talked with the developers behind the feature and it turns out the website I was trying to test for the header had a different behavior set for the calling IP.
Since the editor runs fetch from your browser the IP was different and was not triggering that effect.