Closed kwhitley closed 8 months ago
I do understand the origin mirroring but why do we need a global allowOrigin
var ?
We can just execute in per-request basis, hence, no race-condition.
We can just execute in per-request basis, hence, no race-condition.
It works for me
import { createCors, text, error,Router,json } from 'itty-router'
const router = Router()
router
.get('/', () => text('Hey!'))
function ittyServer(request: Request) {
const { preflight, corsify } = createCors()
const serverFn = middlewareWrapperHandler(
(req) => router.fetch(req).catch(error).then(json),
[
{
preRequest: preflight,
postRequest: corsify,
},
],
)
return serverFn(request)
}
function middlewareWrapperHandler(handler: (request: Request) => Promise<Response>, m: Middleware[]) {
return m.reduce((h, middleware) => {
return async (request) => {
const resp = middleware.preRequest(request) ?? (await h(request))
return middleware.postRequest(resp)
}
}, handler)
}
interface Middleware {
preRequest(req: Request): Response | undefined
postRequest(req: Response): Response
}
export const app = { fetch: ittyServer }
Executing on a per-request basis absolutely does solve the race condition (which exists for origin-mirroring in a scenario where corsify
does not have access to the original request).
That said:
I'm about to start work on a revamp with the following plans:
corsify
will default to not mirror domains - everyone has expressed this is not the expected default behavior anyway, and is really mostly there to serve an edge case (cross-domain cookies, and the high-security crowd). This will allow us to only use the shared var (as a backup) in the case of mirroring, and only when the request was not provided to corsify
... which leads me to:corsify
will be modified to accept (response, request)
. This will allow us to either use it as a drop-in finally
stage handler, or more easily handle the mirror edge-case without having to execute createCors
on a per-request basis (which is a bit heavy).import { AutoRouter, createCors } from 'itty-router'
const { preflight, corsify } = createCors()
const router = AutoRouter({
before: [preflight],
finally: [corsify],
}).get('/', () => 'test')
export default router
import { Router, createCors, json, error } from 'itty-router'
const { preflight, corsify } = createCors()
const router = IttyRouter()
.all('*', preflight)
.get('/', () => 'test')
export default {
fetch: (request, ...args) => router
.fetch(request, ...args)
.then(json)
.catch(error)
.then(response => corsify(response, request))
}
This is being closed as we believed it warranted a complete rewrite #226, and is thus forcing us to bump to a major release under v5.x.
The Issue
The existing CORS procedure is a bit fiddly (requiring a user to manually register an upstream middleware, and a downstream corsify response-modifier).
The existing CORS procedure has a race-condition. In order to mirror the origin in the
allow-origin
response (a good practice, and strictly required in some scenarios), we share a scoped global. This can be polluted if many requests come in at once.The Proposal
I'm proposing a potential rewrite of the process. It should follow the following principles: