Worker Site http request to worker?

Hi All,

I just created a CF worker. It’s Awesome!

I just created a CF Worker Site… It’s Awesome Too!

I tried to make a request from the Worker Site to the CF worker. It failed. Got a CORS method.

Question: How can I take advantage of both worker sites and other workers?

Any help would be greatly appreciated.

Thanks!

-Addam

Sorry… “Got a CORS error”

Keep in mind that subdomains are, by the browser, treated as different domains entirely, so if you make a request from www.mydomain.com to worker.mydomain.com you’ll get a CORS issue.

If you want to allow CORS for your worker, add this header to your worker response header:

Access-Control-Allow-Origin: https://www.mydomain.com

Now you can make a request from www.mydomain.com to worker.mydomain.com

(The browser usually send an OPTIONS request before sending your main request, the OPTIONS request is to check if CORS is allowed, in other words, checking for the Access-Control-Allow-Origin header)

Here’s an excellent article about it and common pitfalls:

2 Likes

Thank you for your response,

I’ve setup the response like this:

async function handleRequests(request) {
  // Make the headers mutable by re-constructing the Request.
  request = new Request(request)
  request.headers.set('Access-Control-Allow-Origin', '*')
  let response = await fetch(URL, request)
  
  response = new Response(response.body, response)
  response.headers.set('Access-Control-Allow-Method', '*')
  response.headers.set('Access-Control-Allow-Origin', 'https:// MY DOMAIN')
  response.headers.set('Access-Control-Allow-Headers', '*')
  console.log("response");
  return response
}
// listen for requests
addEventListener('fetch', event => {
  const { request } = event;
  return event.respondWith(handleRequests(request, request.method));
});

I get this error:

Access to XMLHttpRequest at 'https://...workers.dev/' from origin 'https://...WorkerSite.workers.dev' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Does this make any sense? Thank you again.

-Addam

You might need to check which request type the site is making and respond appropriately to that, see the OPTIONS request in the link I sent.

There is a demo on dealing with CORS preflight available on the developer site:

1 Like

Hi @michael!

Thank you for responding. The demo doesn’t work. :frowning: This is probably one of the most annoying things ever.

Please forgive my frustration. I haven’t had to deal with CORS in years. I didn’t notice it from POSTMAN and that’s how I’ve been working all this time.

OK! I found a bug/issue… I don’t know what side it’s on (browser or CF), BUUUUUTT here is how I resolved and found the issue.

Thanks to the community, I found the code below. It DOES work and DOES fix CORS with workers. WOOOHOOO!! If you place it inside of a worker “AS IS”, it will work.

// An example worker which supports CORS. It passes GET and HEAD
// requests through to the origin, but answers OPTIONS and POST
// requests directly. POST requests must contain a JSON payload,
// which is simply echoed back.

addEventListener('fetch', event => {
  event.respondWith(handle(event.request)
    // For ease of debugging, we return exception stack
    // traces in response bodies. You are advised to
    // remove this .catch() in production.
    .catch(e => new Response(e.stack, {
      status: 500,
      statusText: "Internal Server Error"
    }))
  )
})

async function handle(request) {
  if (request.method === "OPTIONS") {
    return handleOptions(request)
  } else if (request.method === "POST") {
    return handlePost(request)
  } else if (request.method === "GET" || request.method == "HEAD") {
    // Pass-through to origin.
    return fetch(request)
  } else {
    return new Response(null, {
      status: 405,
      statusText: "Method Not Allowed",
    })
  }
}

// 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 or POST requests.
const corsHeaders = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Methods": "GET, HEAD, POST, OPTIONS",
  "Access-Control-Allow-Headers": "Content-Type",
}

function handleOptions(request) {
  if (request.headers.get("Origin") !== null &&
    request.headers.get("Access-Control-Request-Method") !== null &&
    request.headers.get("Access-Control-Request-Headers") !== 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",
      }
    })
  }
}

async function handlePost(request) {
  if (request.headers.get("Content-Type") !== "application/json") {
    return new Response(null, {
      status: 415,
      statusText: "Unsupported Media Type",
      headers: corsHeaders,
    })
  }

  // Detect parse failures by setting `json` to null.
  let json = await request.json().catch(e => null)
  if (json === null) {
    return new Response("JSON parse failure", {
      status: 400,
      statusText: "Bad Request",
      headers: corsHeaders,
    })
  }

  return new Response(JSON.stringify(json), {
    headers: {
      "Content-Type": "application/json",
      ...corsHeaders,
    }
  })
}

Now… THIS code goes into your website/workers site/etc. Be sure to point the URL to your CF worker.

 const Http = new XMLHttpRequest();
    const url='HTTPS://YOUR_CLOUDFLARE_WORKER';
    Http.open("POST", url);
    Http.setRequestHeader('Accept', 'application/json');
    Http.setRequestHeader('Content-Type', 'application/json');
    Http.send('{"test": "GP"}');

    Http.onreadystatechange = (e) => {
      console.log(Http.responseText)
    }

This entire setup works perfectly. Now, HERE is the issue!

IF there is an error ANYWHERE in this code… say for example you swap out the '{"test": "GP"}' with just text that says “nope”, the browser will throw a CORS error and will return an additional error. The confusing part was that originally I was trying to solve the CORS error, not realizing I had an error in the code. In turn, it would throw both. This is also true if you have an error in the worker code as well.

I was able to reproduce it several times over after hours of debugging.

I hope this helps. Happy coding!

-Addam

this happened to me too and wasted hours of my time. Cloudflare please fix this!!!

I don’t think it’s a bug, you probably have to use try/catch on parsing any JSON before returning or it will default to the CORS error first. The error handling could, perhaps, be improved by Cloudflare though.