mtrudel / bandit

Bandit is a pure Elixir HTTP server for Plug & WebSock applications
MIT License
1.67k stars 80 forks source link

Could Bandit support alternative structure than Plug.Conn for underlying HTTP representation? #305

Closed CharlesOkwuagwu closed 7 months ago

CharlesOkwuagwu commented 7 months ago

Re: Bandit.Pipeline.run/6, which will construct a Plug.Conn structure to represent the request and subsequently pass it to the configured Plug module.

This suggests, at this point another module could step in and replace Plug.Conn?

Could Bandit indeed support a non Plug based server, perhaps a more simple and bare bones alternative, if required?

mtrudel commented 7 months ago

I have no immediate plans for this, mostly because being Plug-first is really Bandit's whole mandate. There's really not a whole lot in the Bandit stack today that isn't 100% required by HTTP; the overhead of Plug is negligible in this (the most expensive thing that we could optimize away here are some unnecessary URI.parse calls which end up being pretty expensive, and working to get a faster path for necessary string operations such as lowercasing). If you profile what's in Bandit/Plug today, there's very, very little fat left to trim; I don't really know what a more bare-bones approach might look like. Do you have something in mind?

However, there are two things which may be interesting for you:

  1. I'm midway through a pretty substantial refactor of Bandit's HTTP internals to split out transport concerns from semantic concerns. HTTP/1 and HTTP/2 share the same semantics, and really differ only in how the actual bytes of a request and response are sent back and forth. The changes I'm working on will make this explicit, and will end up sharing the entirety of semantics between the two stacks. Semantics in this case amounts to a shared Bandit.Adapter & a shared Bandit.Pipeline, with a pluggable notion of Bandit.HTTPTransport that allows each protocol to plug its own low-level transport in. This work is arriving in three steps:

    • HTTP/2 is already in main
    • HTTP/1 is in #297
    • The work to de-deuplicate the shared bits into a single shared implementation is currently a work-in-progress, and I haven't pushed it up yet (I will soon though!)
  2. I've had a long-standing wish to extend the Plug API to be able to handle a richer request lifecycle (in order to manage gRPC, SSE, etc). No concrete plans for this, but I'm thinking I might start proofing some stuff later on this year.

mtrudel commented 7 months ago

Going to close this issue for hygiene; feel free to keep chatting here if you'd like!

mtrudel commented 7 months ago

The lower-level HTTPTransport behaviour may be interesting: https://github.com/mtrudel/bandit/blob/816fe4addcb7814baedb33592dc30b58febaf671/lib/bandit/http_transport.ex

CharlesOkwuagwu commented 7 months ago

I have no immediate plans for this, mostly because being Plug-first is really Bandit's whole mandate. There's really not a whole lot in the Bandit stack today that isn't 100% required by HTTP; the overhead of Plug is negligible in this (the most expensive thing that we could optimize away here are some unnecessary URI.parse calls which end up being pretty expensive, and working to get a faster path for necessary string operations such as lowercasing). If you profile what's in Bandit/Plug today, there's very, very little fat left to trim; I don't really know what a more bare-bones approach might look like. Do you have something in mind?

However, there are two things which may be interesting for you:

  1. I'm midway through a pretty substantial refactor of Bandit's HTTP internals to split out transport concerns from semantic concerns. HTTP/1 and HTTP/2 share the same semantics, and really differ only in how the actual bytes of a request and response are sent back and forth. The changes I'm working on will make this explicit, and will end up sharing the entirety of semantics between the two stacks. Semantics in this case amounts to a shared Bandit.Adapter & a shared Bandit.Pipeline, with a pluggable notion of Bandit.HTTPTransport that allows each protocol to plug its own low-level transport in. This work is arriving in three steps:

    • HTTP/2 is already in main
    • HTTP/1 is in Refactor HTTP/1 #297
    • The work to de-deuplicate the shared bits into a single shared implementation is currently a work-in-progress, and I haven't pushed it up yet (I will soon though!)
  2. I've had a long-standing wish to extend the Plug API to be able to handle a richer request lifecycle (in order to manage gRPC, SSE, etc). No concrete plans for this, but I'm thinking I might start proofing some stuff later on this year.

@mtrudel Thanks for this detailed answer

CharlesOkwuagwu commented 3 months ago

... feel free to keep chatting here if you'd like!

@mtrudel it would be great if bandit offered users the option to have a non-plug-based representation for the http-connection.

It gives more flexibility over-all for Bandit