Fix CORS issues in Cloudflare Worker for API

Co-authored-by: collinbarrett <6483057+collinbarrett@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2025-11-15 03:36:12 +00:00 committed by Collin Barrett
parent 533e6156ae
commit 419885c1c5
2 changed files with 101 additions and 2 deletions

View file

@ -1 +1,28 @@
Currently manually copy/paste/deploy via Cloudflare Portal UI.
# Cloudflare Workers
## Deployment
Currently, these workers are manually deployed via the Cloudflare Portal UI:
1. Go to the [Cloudflare Workers dashboard](https://dash.cloudflare.com/)
2. Select the appropriate worker
3. Copy and paste the updated code from the respective `.js` file
4. Click "Save and Deploy"
## filterlists-api-host-rewrite-worker.js
This worker is deployed at `api.filterlists.com` and:
- Proxies requests to the Azure App Service backend
- Handles CORS preflight (OPTIONS) requests
- Adds CORS headers to responses for allowed origins
- Enables Cloudflare edge caching for API responses
### Allowed Origins
- `https://filterlists.com`
- `https://next.filterlists.com`
- `http://localhost:3000`
- Azure Static Web Apps staging environments matching the pattern: `https://nice-water-05873140f-*.eastus2.5.azurestaticapps.net`
**Important**: After updating this file, remember to manually deploy the changes via the Cloudflare Portal UI.

View file

@ -5,6 +5,11 @@ export default {
async fetch(request, _, __) {
const url = new URL(request.url);
// Handle OPTIONS preflight requests for CORS
if (request.method === "OPTIONS") {
return handleOptions(request);
}
const azureHostname = "app-filterlists-directory-prod.azurewebsites.net";
const originUrl = `https://${azureHostname}${url.pathname}${url.search}`;
const originRequest = new Request(originUrl, request);
@ -19,6 +24,73 @@ export default {
},
});
return response;
// Ensure CORS headers are present in the response
return addCorsHeaders(response, request);
},
};
/**
* Handle OPTIONS preflight requests
*/
function handleOptions(request) {
const origin = request.headers.get("Origin");
// Allow CORS from filterlists.com domains and localhost
const allowedOrigins = [
"https://filterlists.com",
"https://next.filterlists.com",
"http://localhost:3000",
];
// Check if origin is allowed or matches staging pattern
const isAllowed = allowedOrigins.includes(origin) ||
(origin && origin.startsWith("https://nice-water-05873140f-") &&
origin.endsWith(".eastus2.5.azurestaticapps.net"));
if (isAllowed) {
return new Response(null, {
status: 204,
headers: {
"Access-Control-Allow-Origin": origin,
"Access-Control-Allow-Methods": "GET, OPTIONS",
"Access-Control-Allow-Headers": request.headers.get("Access-Control-Request-Headers") || "*",
"Access-Control-Max-Age": "86400",
},
});
}
return new Response(null, { status: 403 });
}
/**
* Add CORS headers to response
*/
function addCorsHeaders(response, request) {
const origin = request.headers.get("Origin");
// Allow CORS from filterlists.com domains and localhost
const allowedOrigins = [
"https://filterlists.com",
"https://next.filterlists.com",
"http://localhost:3000",
];
// Check if origin is allowed or matches staging pattern
const isAllowed = allowedOrigins.includes(origin) ||
(origin && origin.startsWith("https://nice-water-05873140f-") &&
origin.endsWith(".eastus2.5.azurestaticapps.net"));
if (!isAllowed) {
return response;
}
// Clone the response so we can modify headers
const newResponse = new Response(response.body, response);
// Set CORS headers
newResponse.headers.set("Access-Control-Allow-Origin", origin);
newResponse.headers.set("Access-Control-Allow-Methods", "GET, OPTIONS");
newResponse.headers.set("Vary", "Origin");
return newResponse;
}