Local development of Cloudflare Workers (Wrangler) and clientside CORS Issues

By Christopher Talke Buscaino at

If you're reading this, you probably just want an answer and the one that I came across that solved this problem for me can be found below:

    // Handle Preflight Requests
    if (request.method === 'OPTIONS') {
        return new Response(null, {
          status: 204,
          headers: {
            'Access-Control-Allow-Credentials': 'true',
            'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Headers': 'Content-Type'
          }
        });
    }

So where would you put this?

I've created a cutdown version of the standard Cloudflare Worker Template below, and inserted the code where you might want to have this when developing locally.

It would probably be a good idea to add a Environment Variable for the CORS Origin header, however, for this use case I just wanted to ensure my client-side http requests were passing pre-flight checks.

export interface Env {
    // Example binding to KV. Learn more at https://developers.cloudflare.com/workers/runtime-apis/kv/
    // MY_KV_NAMESPACE: KVNamespace;
    //
    // Example binding to Durable Object. Learn more at https://developers.cloudflare.com/workers/runtime-apis/durable-objects/
    // MY_DURABLE_OBJECT: DurableObjectNamespace;
    //
    // Example binding to R2. Learn more at https://developers.cloudflare.com/workers/runtime-apis/r2/
    // MY_BUCKET: R2Bucket;
}

export default {
    async fetch(
        request: Request,
        env: Env,
        ctx: ExecutionContext
    ): Promise<Response> {
        return await handleRequest(request, env).catch(
            (err) => new Response(err.stack, { status: 500 })
        )
    },
};

async function handleRequest(request: Request, env: Env) {
    const { pathname } = new URL(request.url);

    // Handle Preflight Requests
    if (request.method === 'OPTIONS') {
        return new Response(null, {
          status: 204,
          headers: {
            'Access-Control-Allow-Credentials': 'true',
            'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Headers': 'Content-Type'
          }
        });
    }

    if (pathname.startsWith("/forms/shipments")) {

        if (request.method === 'POST') {

            return new Response(JSON.stringify({ 
                path: pathname, 
                response: true, 
                method: request.method,
            }), {
                headers: {
                    "Content-Type": "application/json" ,
                    'Access-Control-Allow-Credentials': 'true',
                    'Access-Control-Allow-Origin': '*',
                },
            });
        }

        if (request.method === 'GET') {
            return new Response(JSON.stringify({ 
                path: pathname, 
                response: true, 
                method: request.method,
            }), {
                headers: {
                    "Content-Type": "application/json" ,
                    'Access-Control-Allow-Credentials': 'true',
                    'Access-Control-Allow-Origin': '*',
                },
            });
        }

    }

    return new Response("Does not exist...");
}