* Fix rack.after_reply exceptions breaking connections
Currently, when a `rack.after_reply` callable raises an exception we
attempt to handle it like other client errors by responding with an HTTP
500 response. This however doesn't work because `rack.after_reply`
callbacks are called after the response body has already been written to
the client.
This can cause issues with re-used connections. This is because 2 HTTP
responses are being returned for a single request. If a second HTTP
request is made before the error handling logic completes the timing can
line up causing the second HTTP response to be served a 500 from the
first HTTP requests `rack.after_reply` callbacks raising.
That may look roughly like:
1. Request 1 starts, opening a reusable TCP connection
2. Request 1 is written to and "completed"
3. Request 1 `rack.after_reply` callables are called
4. Request 2 starts, reusing the same TCP connection as request 1
5. `rack.after_reply` raises, calls `client_error` and serves a 500
response
6. Request 2 receives the 500 response.
This is somewhat difficult to reproduce using HTTP clients since it's a
race condition whether or not the 500 is written at the "correct" time
or not.
To prevent this issue the `rack.after_reply` callables are now wrapped
in a begin/rescue/end block that rescues from `StandardError` and logs
instead of attempting to serve a 500 response.
* Assert against less specific exception
Another fallout from https://github.com/puma/puma/pull/2809 is that
in some cases the `res_body.close` wasn't called because some previous code
raised.
For Rails apps it means CurrentAttributes and a few other important
states aren't reset properly.
This is being improved on the Rails side too, but I believe it would
be good to harden this on the puma side as well.
* Always send lowlevel_error response to client
* Add spec for lowlever error handler
* Make sure we have a clean buffer when starting response
* Simplify test
* Rename spec
* Add method docs
* Tweak the test
* Return 500 from lowlevel_error_handler in test
Co-authored-by: Patrik Ragnarsson <patrik@starkast.net>
* Improve parsing of HTTP_HOST header
IPV6 Host was not properly parsed.
https://github.com/puma/puma/issues/2584
* Extracted Regex to constant
* Incorporate feedback
IPV6 are bracketed but contain colons so I needed to adapt the logic to separate host/port.
Co-authored-by: pascal betz <pascal.betz@swisscom.com>