Skip to content

Commit

Permalink
Send content-length header on 5xx (#2304)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kludex authored Apr 13, 2024
1 parent 772c24b commit 0efd383
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 41 deletions.
14 changes: 13 additions & 1 deletion tests/protocols/test_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,19 @@ async def test_max_concurrency(http_protocol_cls: HTTPProtocol):
protocol = get_connected_protocol(app, http_protocol_cls, limit_concurrency=1)
protocol.data_received(SIMPLE_GET_REQUEST)
await protocol.loop.run_one()
assert b"HTTP/1.1 503 Service Unavailable" in protocol.transport.buffer
assert (
b"\r\n".join(
[
b"HTTP/1.1 503 Service Unavailable",
b"content-type: text/plain; charset=utf-8",
b"content-length: 19",
b"connection: close",
b"",
b"Service Unavailable",
]
)
== protocol.transport.buffer
)


@pytest.mark.anyio
Expand Down
38 changes: 14 additions & 24 deletions uvicorn/protocols/http/flow_control.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import asyncio

from uvicorn._types import (
ASGIReceiveCallable,
ASGISendCallable,
HTTPResponseBodyEvent,
HTTPResponseStartEvent,
Scope,
)
from uvicorn._types import ASGIReceiveCallable, ASGISendCallable, Scope

CLOSE_HEADER = (b"connection", b"close")

Expand Down Expand Up @@ -45,20 +39,16 @@ def resume_writing(self) -> None:
self._is_writable_event.set()


async def service_unavailable(scope: "Scope", receive: "ASGIReceiveCallable", send: "ASGISendCallable") -> None:
response_start: "HTTPResponseStartEvent" = {
"type": "http.response.start",
"status": 503,
"headers": [
(b"content-type", b"text/plain; charset=utf-8"),
(b"connection", b"close"),
],
}
await send(response_start)

response_body: "HTTPResponseBodyEvent" = {
"type": "http.response.body",
"body": b"Service Unavailable",
"more_body": False,
}
await send(response_body)
async def service_unavailable(scope: Scope, receive: ASGIReceiveCallable, send: ASGISendCallable) -> None:
await send(
{
"type": "http.response.start",
"status": 503,
"headers": [
(b"content-type", b"text/plain; charset=utf-8"),
(b"content-length", b"19"),
(b"connection", b"close"),
],
}
)
await send({"type": "http.response.body", "body": b"Service Unavailable", "more_body": False})
28 changes: 12 additions & 16 deletions uvicorn/protocols/http/httptools_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
ASGIReceiveEvent,
ASGISendEvent,
HTTPRequestEvent,
HTTPResponseBodyEvent,
HTTPResponseStartEvent,
HTTPScope,
)
Expand Down Expand Up @@ -435,21 +434,18 @@ async def run_asgi(self, app: ASGI3Application) -> None:
self.on_response = lambda: None

async def send_500_response(self) -> None:
response_start_event: HTTPResponseStartEvent = {
"type": "http.response.start",
"status": 500,
"headers": [
(b"content-type", b"text/plain; charset=utf-8"),
(b"connection", b"close"),
],
}
await self.send(response_start_event)
response_body_event: HTTPResponseBodyEvent = {
"type": "http.response.body",
"body": b"Internal Server Error",
"more_body": False,
}
await self.send(response_body_event)
await self.send(
{
"type": "http.response.start",
"status": 500,
"headers": [
(b"content-type", b"text/plain; charset=utf-8"),
(b"content-length", b"21"),
(b"connection", b"close"),
],
}
)
await self.send({"type": "http.response.body", "body": b"Internal Server Error", "more_body": False})

# ASGI interface
async def send(self, message: ASGISendEvent) -> None:
Expand Down

0 comments on commit 0efd383

Please sign in to comment.