Summary
When a client sends Connection: close, Stallion correctly closes the TCP connection after the response, but does not advertise the close intent in the response headers. Per RFC 9112 §9.6:
A server that receives a "close" connection option MUST initiate closure of the connection (see Section 9.6) after it sends the final response to the request that contained "close". The server SHOULD send a "close" connection option in its final response on that connection.
Stallion satisfies the MUST (the server does close). It does not satisfy the SHOULD.
Reproduction
Request bytes:
GET / HTTP/1.1\r\n
Host: example.com\r\n
Connection: close\r\n
\r\n
Response bytes from a minimal Stallion app:
HTTP/1.1 200 OK\r\n
Content-Type: text/plain\r\n
Content-Length: 3\r\n
\r\n
ok\n
There is no Connection: close in the response, even though the server does close the TCP connection after sending these bytes. A client reading the headers alone cannot tell that the connection will be closed; it has to infer from EOF.
For comparison on the same request (curl, which handles TCP framing without the quirks we hit using nc):
| Server |
Connection: close in response |
| nginx |
yes |
| apache |
yes |
| caddy |
yes |
| cowboy |
yes |
| lighttpd |
yes |
| hyper |
yes |
| haproxy |
yes |
| bandit |
no |
| stallion |
no |
Summary
When a client sends
Connection: close, Stallion correctly closes the TCP connection after the response, but does not advertise the close intent in the response headers. Per RFC 9112 §9.6:Stallion satisfies the MUST (the server does close). It does not satisfy the SHOULD.
Reproduction
Request bytes:
Response bytes from a minimal Stallion app:
There is no
Connection: closein the response, even though the server does close the TCP connection after sending these bytes. A client reading the headers alone cannot tell that the connection will be closed; it has to infer from EOF.For comparison on the same request (curl, which handles TCP framing without the quirks we hit using
nc):Connection: closein response