kwhitley / itty-router

A little router.
MIT License
1.75k stars 78 forks source link

HEAD and OPTIONS request support #87

Closed markusahlstrand closed 2 years ago

markusahlstrand commented 2 years ago

Just assumed that the router supported head requests, but realised that it doesn't. Is this by design or has it not just been implemented yet? Think head and options support would be nice to have as default, but guess it could be added as a proxy instead? What would be the preferred solution?

kwhitley commented 2 years ago

It does handle these just fine (for example many folks, myself included, have itty handling CORS)... nothing specifically is built into itty around any type of request (or almost anything regarding the request itself), but the proxy allows you to target virtually any request method imaginable!

Mind sharing your code that you're having the issue with?

markusahlstrand commented 2 years ago

Hi and thanks for the quick reply :)

When using other node routers like express or koa-router the router will automagically handle requests with good defaults. If you do a HEAD request and the router has a GET route defined it will execute that route and return the response without the body. If you a POST request and there's only a GET route defined it will return a 405. It will also automagically handle OPTIONS request with the correct response as it already has this info.

I understand that this could be achieved with the Proxy but it's a significant amount of work to get this right and think it would be better to have it implemented as part of the router itself.

What are your thoughts?

kwhitley commented 2 years ago

Oh yeah, that would definitely be in the purview of a downstream layer... itty itself doesn't even have a concept of a Response (internally). It awaits/executes handler functions until anything is returned, which terminates the chain - of course I assume nearly everyone uses that to return a Response. This is extremely powerful in that itty can be used for a ton of other use-cases than just request/response routing, but that unopinionated nature (along with the ~500 byte size) means some of the magic of much more feature-rich routers won't be there, yet we restrain/restrict none of the power that those do. For example, you can send any number of params to router.handle, and they'll be passed through to all handlers because we don't have a true express-like signature of (request, response, next)... the only thing we are opinionated about is that there should be at least one param, that has a method and url on it (a Request-like object). That's it!

To simplify all the response creation (that itty does not include), and add quality of life middlewares, we have https://www.npmjs.com/package/itty-router-extras (I never use itty without it personally).

Our original vision was the most absurdly tiny routing that handled the majority (not all) of use cases with an elegant interface, in as few bytes as possible - while leaving it flexible to be used as the tiny internal core to other more rich routers. We have regex parsed route params (with some limitations) and sync/async flow, middleware support, etc, all for 500 bytes... the regex libraries alone from other libs are often into the several KB territory :)

kwhitley commented 2 years ago

If you wanted to use the itty request flow internals but add your magic, and had any intention of sharing it back out publicly, I'd recommend either a single upstream middleware (perhaps for the .all channel) as the least invasive/restrictive, or if you need to intercept the final return/response after the .handle, perhaps an entire Proxy around itty itself (which of course could preload any middleware you needed). By doing so, you could use the request (that's passed through handlers) as the carrier agent of whatever info you needed to build/modify the final response after it's returned.

Make sense? Happy to assist where I can if you want to tackle something like this!

markusahlstrand commented 2 years ago

It's a good point and indeed neat that it doesn't have any dependency on Response at all.

The downside it that in order to make for instance a good OPTIONS handler it would need to be able to return all matching routes. Maybe this more http-specific implementation would require a fundamentally different approach where you could yield matching routes?

kwhitley commented 2 years ago

Hmmm, if you need to intercept OPTIONS request for a specific route that you've registered (to say, GET), rather than a wildcard scenario on OPTIONS (much easier), I'd have to give it some thought. As to the much easier/less-controlled approach, heres are some vaguely related issues/discussions that may (I hope) help...

65 #70

kwhitley commented 2 years ago

Closing this for now, but should remain as food for thought for the CORS handling implementation I'm working on (as I get time, which is scarce)!

Thanks for the discussion!!! :)