kwhitley / itty-cors

Dead-simple CORS handling for any itty-router API (test with Cloudflare Workers, but works anywhere)!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Simple usage example does not work for me

dandaka opened this issue · comments

Now

const { preflight, corsify } = createCors()

gives error

TypeError: Cannot read properties of undefined (reading 'origins')

Working for me

const { preflight, corsify } = createCors({ origins: ['*'] })

Same issue on my side, @dandaka thanks for the workaround

Also, I was expecting "simple usage" to enable CORS on all routes, did not work for me.

Did not work here either.

Argument of type '(r: Request<unknown>) => Response' is not assignable to parameter of type 'RouteHandler'.   Types of parameters 'r' and 'request' are incompatible.

Here's how I managed to set up CORS on an individual route:

import { Router } from 'itty-router';
import { createCors } from 'itty-cors';
import {json} from 'itty-router-extras'
const { preflight, corsify } = createCors({
  methods: ['POST'],
  origins: ['*'],
  maxAge: 3600,

})
const router = Router();

const handleFunc = async req =>  {
//process
   return json(({success: true}));
}

//...
router.post('/api/whatever', preflight, async req => handleFunc(req).then(corsify));
//...
export default {
  fetch: (...args) => router
		.handle(...args)
		.catch(err => error(500, err.stack))
}

I hope that helps, it runs ok on CloudFlare workers so far. The trick was to add .then after the handler function in the route.

I am having issues on CF. Here is my handler code:

import {
  error,
  Router
} from 'itty-router'
import { createCors } from 'itty-cors'

const { preflight, corsify } = createCors({
  methods: ['POST'],
  origins: ['*'],
  maxAge: 3600
})

const router = Router()
router.all('*', preflight)

// ... more routes, some router.post()

export default {
  fetch: (...args) => router.handle(...args).catch(error).then(corsify)
}

On same origin, it's fine.

I am noticingAccess-Control-Allow-Origin: http://localhost:8787, when I think it should be * or the host I am coming from. Is * even allowed for POST on current chrome? I don't think it qualifies as a "simple request".

This is the error I get on a POST in another origin:

Access to fetch at 'http://localhost:8787/' from origin 'https://SOMETHINGELSE' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'http://localhost:8787' that is not equal to the supplied origin. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I can make a very simple repro, if it helps.

Here is a simple repro:
https://github.com/konsumer/cf-itty-cors-example

Am I missing a step?

Here is request from https://example.com origin:

Screenshot 2024-01-27 at 4 13 08 PM

Here is from same-origin:

Screenshot 2024-01-27 at 4 17 28 PM

It doesn't seem to be setting Access-Control-Allow-Origin even if I do this:

const { preflight, corsify } = createCors({
  methods: ['POST'],
  origins: ['https://example.com'],
  maxAge: 3600
})
HTTP/1.1 200 OK
Content-Length: 33
Content-Type: application/json; charset=utf-8
Access-Control-Allow-Methods: POST
Access-Control-Max-Age: 3600

corsify() takes a response and returns a modified response. Here's a typical usage scenario:

import { Router } from 'itty-router';
import { createCors } from 'itty-cors';

// Create CORS handlers
const { preflight, corsify } = createCors();

// Create a new router
const router = Router();

// Handle CORS preflight requests
router.all('*', preflight);

// Process GET request
router.get('/endpoint', async ({ params, query }, env) => {
  // Return CORSified response
  const responseData = { ... };
  return corsify(new Response(
    JSON.stringify(responseData),
    {
      headers: { 'Content-Type': 'application/json' },
      status: 200,
      statusText: 'OK',
    }
  ));
});

// Handle undefined routes
router.all('*', () => new Response('404'));

export default {
  fetch: router.handle,
};

@thdoan Wouldn't this do the same thing?
https://github.com/konsumer/cf-itty-cors-example/blob/main/src/index.js#L36

It's in the then, so it takes the response and wraps it.

Btw folks, itty-cors has been deprecated in favor of the built-in cors() (which is more safe, has more control options, and is ~20% smaller) in itty-router v5.

https://itty.dev/itty-router/cors

@kwhitley Cool, I didn't realize v5 came out. I'd prefer to use built-in as well.