- Timeouts encountered while reading a request body will now result in a
408 Request Timeout
being returned to the client by way of aBandit.HTTPError
being raised. Previously, a:more
tuple was returned (#385, thanks @martosaur!)
- Improve handling of the end of stream condition for HTTP/2 requests that send a body which isn't read by the Plug (#387, thanks @fekle!)
- Add
domain: [:bandit]
to the metadata of all logger calls - Bring logging of early-connect HTTP2 errors under the
log_protocol_errors
umbrella
- Raise HTTP/2 send window timeouts as stream errors so that they're logged as protocol errors (thanks @hunterboerner!)
- Add
:short
and:verbose
options tolog_protocol_errors
configuration option. Change default value to:short
, which will log protocol errors as a single summary line instead of a full stack trace - Raise
Bandit.HTTPError
errors when attempting to write to a closed client connection (except for chunk/2 calls, which now return{:error, reason}
). Unless otherwise caught by the user, these errors will bubble out past the configured plug and terminate the plug process. This closely mimics the behaviour of Cowboy in this regard (#359) - Respect the plug-provided content-length on HEAD responses (#353, thanks @meeq!)
- Minor changes to how 'non-system process dictionary entries' are identified
- No longer closes on HTTP/1 requests smaller than the size of the HTTP/2 preamble
- Close deflate contexts more eagerly for reduced memory use
- Don't crash on non-stringable process dictionary keys (#350, thanks @ryanwinchester, @chrismccord!)
- Process dictionary is now cleared of all non-system process dictionary entries between keepalive requests (#349)
- Explicitly run a GC before upgrading a connection to websocket (#348)
- Improve docs around deflate options (thanks @kotsius!)
- Bandit now respects an exception's conformance to
Plug.Exception
when determining which status code to return to the client (if the plug did not already send one). Previously they were always returned as 500 (for HTTP/1) or an 'internal error' stream error (for HTTP/2) - Bandit now only logs the stacktrace of plug-generated exceptions whose status
code (as determined by
Plug.Exception.status/1
) is contained within the newlog_exceptions_with_status_codes
configuration option (defaulting to500..599
) - As a corollary to the above, Bandit request handler processes no longer exit abnormally in the case of plug-generated exceptions
- HTTP semantic errors encountered in an HTTP/2 request are returned to the client using their proper status code instead of as a 'protocol error' stream error
- Support top-level :inet and :inet6 options for Plug.Cowboy compatibility (#337)
- BREAKING CHANGE Move
log_protocol_errors
configuration option into sharedhttp_options
top-level config (and apply it to HTTP/2 errors as well) - BREAKING CHANGE Remove
origin_telemetry_span_context
from WebSocket telemetry events - BREAKING CHANGE Remove
stream_id
from HTTP/2 telemetry events - Add
conn
to the metadata of telemetry start events for HTTP requests - Stop sending WebSocket upgrade failure reasons to the client (they're still logged)
- Return HTTP semantic errors to HTTP/2 clients as protocol errors instead of internal errors
Warning
IMPORTANT Phoenix users MUST upgrade to WebSockAdapter 0.5.6
or newer when
upgrading to Bandit 1.4.0
or newer as some internal module names have changed
- Complete refactor of HTTP/2. Improved process model is MUCH easier to understand and yields about a 10% performance boost to HTTP/2 requests (#286 / #307)
- Substantial refactor of the HTTP/1 and HTTP/2 stacks to share a common code
path for much of their implementations, with the protocol-specific parts being
factored out to a minimal
Bandit.HTTPTransport
protocol internally, which allows each protocol to define its own implementation for the minimal set of things that are different between the two stacks (#297 / #329)
- BREAKING CHANGE Move configuration options that are common between HTTP/1
and HTTP/2 stacks into a shared
http_options
top-level config - BREAKING CHANGE The HTTP/2 header size limit options have been deprecated,
and have been replaced with a single
max_header_block_size
option. The setting defaults to 50k bytes, and refers to the size of the compressed header block as sent on the wire (including any continuation frames) - BREAKING CHANGE Remove
req_line_bytes
,req_header_bytes
,resp_line_bytes
andresp_header_bytes
from HTTP/1 request telemetry measurements - BREAKING CHANGE Remove
status
,method
andrequest_target
from telemetry metadata. All of this information can be obtained from theconn
struct attached to most telemetry events - BREAKING CHANGE Re-reading a body that has already been read returns
{:ok, "", conn}
instead of raising aBandit.BodyAlreadyReadError
- BREAKING CHANGE Remove
Bandit.BodyAlreadyReadError
- BREAKING CHANGE Remove h2c support via Upgrade header. This was deprecated in RFC9113 and never in widespread use. We continue to support h2c via prior knowledge, which remains the only supported mechanism for h2c in RFC9113
- Treat trailing bytes beyond the indicated content-length on HTTP/1 requests as an error
- Surface request body read timeouts on HTTP/1 requests as
{:more...}
tuples and not errors - Socket sending errors are no longer surfaced on chunk sends in HTTP/1
- We no longer log if processes that are linked to an HTTP/2 stream process terminate unexpectedly. This has always been unspecified behaviour so is not considered a breaking change
- Calls of
Plug.Conn
functions for an HTTP/2 connection must now come from the stream process; any other process will raise an error. Again, this has always been unspecified behaviour - We now send an empty DATA frame for explicitly zero byte bodies instead of optimizing to a HEADERS frame with end_stream set (we still do so for cases such as 204/304 and HEAD requests)
- We now send RST_STREAM frames if we complete a stream and the remote end is still open. This optimizes cases where the client may still be sending a body that we never consumed and don't care about
- We no longer explicitly close the connection when we receive a GOAWAY frame
- Run an explicit garbage collection between every 'n' keepalive requests on the same HTTP/1.1 connection in order to keep reported (but not actual!) memory usage from growing over time. Add
gc_every_n_keepalive_requests
option to configure this (default value of5
). #322, thanks @ianko & @Nilsonn!) - Add
log_protocol_errors
option to optionally quell console logging of 4xx errors generated by Bandit. Defaults totrue
for now; may switch tofalse
in the future based on adoption (#321, thanks @Stroemgren!)
- Don't send a
transfer-encoding
header for 1xx or 204 responses (#317, thanks @mwhitworth!)
- Log port number when listen fails (#312, thanks @jonatanklosko!)
- Accept mixed-case keepalive directives (#308, thanks @gregors!)
- Reset Logger metadata on every request
- Disable logging of unknown messages received by an idle HTTP/1 handler to
avoid noise on long polling clients. This can be changed via the
log_unknown_messages
http_1 option (#299)
- Automatically pull in
:otp_app
value in Bandit.PhoenixAdapter (thanks @krns!) - Include response body metrics for HTTP/1 chunk responses
- Fix broken HTTP/1 inform/3 return value (thanks @wojtekmach!)
- Maintain HTTP/1 read timeout after receiving unknown messages
- Do not send a fallback response if the plug has already sent one (#288 & #289, thanks @jclem!)
- Packagaing improvements (#283, thanks @wojtekmach!)
- Fix support for proplist-style arguments (#277, thanks @jjcarstens!)
- Speed up WebSocket framing (#272, thanks @crertel!)
- Fix off-by-one error in HTTP2 sendfile (#269, thanks @OrangeDrangon!)
- Improve mix file packaging (#266, thanks @patrickjaberg!)
- Do not advertise disabled protocols via ALPN (#263)
- Messages sent to Bandit HTTP/1 handlers no longer intentionally crash the handler process but are now logged in the same manner as messages sent to a no-op GenServer (#259)
- Messages regarding normal termination of monitored processes are no longer
handled by the WebSocket handler, but are now passed to the configured
c:WebSock.handle_info/2
callback (#259)
- Add support for
Phoenix.Endpoint.server_info/1
(now in Phoenix main; #258) - Add support for
:max_heap_size
option in WebSocket handler (introduced in websock_adapter 0.5.5; #255, thanks @v0idpwn!)
- Remove internal tracking of remote
max_concurrent_streams
setting (#248)
- Fix startup when plug module has not yet been loaded by the BEAM
- Support function based plugs & improve startup analysis of plug configuration (#236)
- Improve keepalive support when Plug does not read request bodies (#244)
- Improve logic around not sending bodies on HEAD requests (#242)
- Internal refactor of WebSocket validation (#229)
- Use protocol default port in the event that no port is provided in host header (#228)
- Improve handling of iolist response bodies (#231, thanks @travelmassive!)
- Fix issue with setting remote IP at connection startup (#227, thanks @jimc64!)
- Add
Bandit.PhoenixAdapter.bandit_pid/2
(#212) - Return errors to
Plug.Conn.Adapter.chunk/2
HTTP/1 calls (#216)
Plug.Conn
function calls must come from the process on whichPlug.call/2
was called (#217, reverts #117)
- Add ability to send preamble frames when closing a WebSock connection (#211)
- Bump ThousandIsland to 1.0.0-pre.7 to fix leaking file descriptors on
Plug.Conn.sendfile/5
calls (thanks @Hermanverschooten!)
- BREAKING CHANGE Move
conn
value in telemetry events from measurements to metadata
- Add
method
,request_target
andstatus
fields to telemetry metadata on HTTP stop events - Improve RFC compliance regarding cache-related headers on deflated responses (#207, thanks @tanguilp!)
- Bump to Thousand Island
1.0.0-pre.6
- Doc improvements (particularly around implementation notes)
- Typespec improvements (thanks @moogle19!)
- Add support for
Plug.Conn.inform/3
on HTTP/1 connections (#180) - Add support for h2c upgrades (#186, thanks @alisinabh!)
- Internal refactoring of HTTP/1 content-length encoded body reads (#184, #190, thanks @asakura & @moogle19!)
- Bump Thousand Island to 1.0.0-pre.6 (gaining support for suspend/resume API)
- Drop Elixir 1.12 as a supported target (it should continue to work, but is no longer covered by CI)
- Fix crash when Plug used
Plug.Conn.get_peer_data/1
function on HTTP/1 connections (#170, thanks @moogle19!) - Fix port behaviour when connecting over unix socket (#176, thanks @asakura & @ibarchenkov!)
- Use new ThousandIsland APIs for socket info (#167, thanks @asakura!)
- Handle nil connection close reason when closing a WebSocket
- Further improve logging on WebSocket upgrade errors (#149)
- Refactor HTTP/1 read routines (#158 & #166, thanks @asakura!)
- Improve logging on WebSocket upgrade errors (#149)
- Override any content-length headers that may have been set by Plug (#165)
- Send content-length on HTTP/2 responses where appropriate (#165)
- Send correct content-length header when sending deflated response (#151)
- Do not attempt to deflate if Plug sends a content-encoding header (#165)
- Improve corner case handling of content-length request header (#163, thanks @ryanwinchester!)
- Handle case where ThousandIsland returns error tuples on some helper routines (#162)
- Always use the declaed scheme if declared in a request-line or
:scheme
pseudo-header (#159) - Internal tidying (thanks @asakura!)
- Total overhaul of typespecs throughout the library (thanks @asakura!)
- Performance / correctness improvements to header length validation (#143, thanks @moogle19!)
- Performance improvements to host header port parsing (#145 & #147, thanks @ryanwinchester!)
- Improve WebSocket upgrade failure error messages to aid in diagnosis (#152)
- Consolidate credo config (#146, thanks @ryanwinchester!)
- Fix error in suggested version dependencies during 1.0-pre series (#142, thanks @cvkmohan!)
- Respect read timeout for HTTP/1 keepalives (#140)
- Support Websock 0.5.1, including support for optional
c:WebSock.terminate/2
(#131)
- Use Req instead of Finch in tests (#137)
- Improve a few corner cases in tests (#136)
- Don't require transport_options to be a keyword list (#130, thanks @justinludwig!)
- Update Thousand Island dependency to 1.0-pre
- Bandit will now raise an error at startup if no plug is specified in config (thanks @moogle19!)
- Fix crash at startup when using
otp_app
option (thanks @moogle19!) - Minor doc formatting fixes
- BREAKING CHANGE Rename top-level
options
field tothousand_island_options
- BREAKING CHANGE Rename
deflate_opts
todeflate_options
where used - Massive overhaul of documentation to use types where possible
- Bandit now uses a term of the form
{Bandit, ref()}
forid
in our child spec - Bumped to Thousand Island 0.6.7.
num_connections
is now 16384 by default
- Added top level support for the following convenience parameters:
port
can now be set at the top level of your configurationip
can now be set at the top level of your configurationkeyfile
andcertfile
can now be set at the top level of your configuration
- Transport options are now validated by
Plug.SSL.configure/1
when starting an HTTPS server - Rely on Thousand Island to validate options specified in
thousand_island_options
. This should avoid cases like #125 in the future.
- Drop explicit support for Elixir 1.11 since we no longer test it in CI (should still work, just that it's now at-your-own-risk)
- Add logo to ex_doc and README
- Allow access to Thousand Island's underlying
shutdown_timeout
option - Fix test errors that cropped up in OTP 26
- Calling
Plug.Conn
adapter functions for HTTP/2 based requests are no longer restricted to being called from the process which calledc:Plug.call/2
- Added
startup_log
to control whether / how Bandit logs the bound host & port at startup (Thanks @danschultzer) - Improved logging when the configured port is in use at startup (Thanks @danschultzer)
- Update to Thousand Island 0.6.5
- Added advanced
handler_module
configuration option tooptions
- Support returning
x-gzip
as negotiatedcontent-encoding
(previously would negotiate a request forx-gzip
asgzip
)
- Added HTTP compression via 'Content-Encoding' negotiation, enabled by default. Configuration is available; see Bandit docs for details
- Minor refactor of internal HTTP/2 plumbing. No user visible changes
- Update documentation & messaging to refer to RFC911x RFCs where appropriate
- Validate top-level config options at startup
- Revise Phoenix adapter to support new config options
- Doc updates
- Add configuration points for various parameters within the HTTP/1, HTTP/2 and WebSocket stacks. See Bandit docs for details
- Modified telemetry event payloads to match the conventions espoused by
:telemetry.span/3
- Default shutdown timeout is now 15s (up from 5s)
- Update to Thosuand Island 0.6.4 (from 0.6.2)
- Support explicit setting of WebSocket close codes & reasons as added in WebSock 0.5.0
- Add comprehensive Telemetry support within Bandit, as documented in the
Bandit.Telemetry
module - Update our ThousandIsland dependnecy to pull in Thousand Island's newly
updated Telemetry support as documented in the
ThousandIsland.Telemetry
module - Fix parsing of host / request headers which contain IPv6 addresses (#97). Thanks @derekkraan!
- Use Plug's list of response code reason phrases (#96). Thanks @jclem!
- Minor doc updates
- Close WebSocket connections with a code of 1000 (instead of 1001) when shutting down the server (#89)
- Use 100 acceptor processes by default (instead of 10)
- Improvements to make WebSocket frame masking faster
- Remove logging entirely when client connections do not contain a valid protocol
- Refactor WebSocket support for about a 20% performance lift
- Add
nodelay
option to test suite to fix artificially slow WebSocket perf tests
- Log useful message when a TLS connection is made to plaintext server (#74)
- Update Thousand Island to 0.5.15 (quiets logging in timeout cases)
- Quiet logging in when client connections do not contain a valid protocol
- Refactor HTTP/1 for about a 20% performance lift
- Add WebSocket support to CI benchmark workflow
- Doc updates
- Allow multiple instances of Bandit to be started in the same node (#75)
- Improve error handling in HTTP/1 when protocol errors are encountered (#74)