Skip to content

Instantly share code, notes, and snippets.

@pkieltyka
Last active November 30, 2022 14:37
Show Gist options
  • Save pkieltyka/d6830df1f95ba5d2fbdef89847804060 to your computer and use it in GitHub Desktop.
Save pkieltyka/d6830df1f95ba5d2fbdef89847804060 to your computer and use it in GitHub Desktop.
//
// CORS Anywhere -- Cloudflare Workers edition!
//
// try: https://cors-anywhere.0xhorizon.workers.dev/https://discordapp.com/api/guilds/444586810765475860/widget.json
//
addEventListener('fetch', event => {
event.respondWith(handleRequest(event, event.request))
})
async function handleRequest(event, request) {
// Handle OPTIONS request quickly
if (request.method === "OPTIONS") {
return handleCORSPreflight(request)
} else if (request.method !== "GET" && request.method !== "HEAD") { //&& request.method !== "POST") {
return new Response(null, {
status: 405,
statusText: "Method Not Allowed",
})
}
// Handle normal GET/HEAD request
let url = new URL(request.url)
let host = url.host
let param = url.pathname
if (param.length >= 1) {
param = param.substr(1)
}
if (param === "") {
return respondWithText("welcome")
}
if (!param.startsWith("http")) {
return respondWithText("Oops! invalid use, speak to dev team for correct usage.")
}
if (param.indexOf("://") < 0) {
param = param.replace("http:/", "http://")
param = param.replace("https:/", "https://")
}
// Proxy-cache the request (with ttl of 60 seconds)
let cacheUrl = new URL(param)
let cacheKey = new Request(cacheUrl)
let cache = caches.default
// Get this request from this zone's cache
let resp = await cache.match(cacheKey)
if (!resp) {
//if not in cache, grab it from the origin
originResp = await fetch(cacheUrl, {
method: request.method,
headers: {
...request.headers
},
cf: {
cacheEverything: true,
cacheTtl: 61,
scrapeShield: false
}
})
// must use Response constructor to inherit all of response's fields
resp = new Response(originResp.body, {
status: originResp.status
})
// copy over certain headers, but we don't want all..
let v = originResp.headers.get('content-type')
if (v && v !== '') {
resp.headers.set('content-type', v)
}
// set caching and cors headers
resp.headers.set('X-Worker', (new Date()).toUTCString())
resp.headers.set('Cache-Control', 'public, max-age=61')
resp.headers.set('Access-Control-Allow-Origin', '*')
resp.headers.set('Access-Control-Allow-Methods', 'GET, HEAD')
// store the fetched response as cacheKey
await cache.put(cacheKey, resp.clone())
}
return resp
}
function respondWithText(text) {
return new Response(text, { status: 200, headers: { "Content-Type": "text/html" } })
}
// We support the GET, POST, HEAD, and OPTIONS methods from any origin,
// and accept the Content-Type header on requests. These headers must be
// present on all responses to all CORS requests. In practice, this means
// all responses to OPTIONS requests.
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, HEAD, POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
}
function handleCORSPreflight(request) {
if (request.headers.get("Origin") !== null &&
request.headers.get("Access-Control-Request-Method") !== null) {
// Handle CORS pre-flight request.
return new Response(null, {
headers: corsHeaders
})
} else {
// Handle standard OPTIONS request.
return new Response(null, {
headers: {
"Allow": "GET, HEAD, POST, OPTIONS",
}
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment