cask icon indicating copy to clipboard operation
cask copied to clipboard

[request] Some mechanism to add CORS-rules to an endpoint/a router/everything.

Open megri opened this issue 5 years ago • 3 comments

Here's what I've found so far:

  • Adding a custom decorator won't work for OPTIONS-requests as the routes are tried before the decorators come into play.
  • Overriding the Main#defaultHandler seems to be the way forward but this feels very "low-level" and introduces some concern-splitting

I'm willing to do some legwork here but I'd like to know if you have any ideas on how this can best be solved.

megri avatar May 04 '20 21:05 megri

Overriding the Main#defaultHandler seems to be the way forward but this feels very "low-level" and introduces some concern-splitting

Would it be possible to put into a trait? I could imagin that a user who needs cors could just mix in the trait to their routes.

jodersky avatar May 06 '20 15:05 jodersky

I think it's a bit trickier—but I may be wrong.

To add CORS in a somewhat convenient manner we'd need to:

  • For simple requests, make sure we attach the proper response headers;
  • For preflighted requests
    • intercept OPTIONS requests for all routes and attach an Access-Control-Allow-Methods response header, listing all methods defined on the endpoint;
    • allow configuration of the Origin header and filter incoming requests based and
      1. attach an Access-Control-Allow-Origin with the correct origin if it is allowed or;
      1. reject(?) the request (not sure exactly, I'm new to the CORS specification);
  • also handle/attach headers for Access-Control-Allow-Headers and such.

Preferably it should be possible to configure at least some of these aspects.

To get access to an endpoint's allowed methods the only way I found was to apply the CORS-rules to cask.Main by overriding defaultHandler : non-endpoint decorators do not have information about the downstream endpoint, and from my experiments there can only be one endpoint decorator for any given route. This also means the interface you're working against is the underlying undertow (I feel potential in creating more abstraction here, to make it possible to inject custom handling/filtering at the edge of cask, but that's a story on its own.)

Perhaps it is possible to wrap an endpoint decorator with a cors-decorator? That would make things slightly simpler—provided the cors-decorator can access the endpoint-decorator—but would still have to be repeated for all endpoints of a route, as I see no way to automatically attach one.

megri avatar May 07 '20 12:05 megri

FYI, I've built a CorsHandler that works in initial tests. See:

  • https://github.com/objektwerks/cask/blob/master/src/main/scala/objektwerks/handler/CorsHandler.scala
  • https://github.com/objektwerks/cask/blob/master/src/main/scala/objektwerks/Server.scala

Naturally, this can be built multiple ways. Note how a CorsHandler is initialized in Server, which extends cask.Main.

objektwerks avatar Mar 07 '22 12:03 objektwerks