Drop the (HTTP/1.1) connection belonging to the current Quart request.
()
| 43 | |
| 44 | |
| 45 | async def drop_connection(): |
| 46 | """Drop the (HTTP/1.1) connection belonging to the current Quart request.""" |
| 47 | # We need to do two things: |
| 48 | # - Convince hypercorn (specifically, around HTTPStream.app_send()) |
| 49 | # that it doesn't need to send a 500 and can just close the socket. |
| 50 | # - Convince h11's state machine that it's okay to close the socket |
| 51 | # without sending a response. |
| 52 | # We can't do this at the ASGI layer: hypercorn will insert the 500 |
| 53 | # for protocol compliance if the ASGI app doesn't provide a |
| 54 | # response. We need to modify the actual HTTP server, either with a |
| 55 | # pull request or by digging into its internals as follows: |
| 56 | # - Grab the HTTPStream whose bound method app_send was passed into |
| 57 | # the Quart request |
| 58 | # - Grab the H11Protocol whose bound method stream_send was passed |
| 59 | # into the HTTPStream's constructor |
| 60 | # - Tell the H11Protocol's underlying h11 state machine to act as if |
| 61 | # the remote side errored, so it thinks dropping the connection is |
| 62 | # the appropriate next step and not misbehavior on our end |
| 63 | # - Tell the HTTPStream to move the state machine forward with no |
| 64 | # further send on our side, which will drop the connection (and |
| 65 | # not consider it for keepalive) |
| 66 | import hypercorn.protocol as hp |
| 67 | |
| 68 | http_stream: hp.http_stream.HTTPStream = request._send_push_promise.args[0].__self__ |
| 69 | protocol: hp.h11.H11Protocol = http_stream.send.__self__ |
| 70 | protocol.connection._process_error(protocol.connection.their_role) |
| 71 | await http_stream.send(hp.events.EndBody(stream_id=http_stream.stream_id)) |
| 72 | await http_stream.app_send(None) |
| 73 | |
| 74 | # Some other things I tried, kept for reference: |
| 75 | # http_stream.state = hypercorn.protocol.http_stream.ASGIHTTPState.RESPONSE |
| 76 | # await http_stream._send_closed() |
| 77 | # http_stream.state = hypercorn.protocol.http_stream.ASGIHTTPState.CLOSED |
| 78 | |
| 79 | |
| 80 | # The following GitHub API datatypes are complete enough to satisfy |