You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
maghoff opened this issue
Sep 4, 2017
· 2 comments
Labels
A-serverArea: server.C-bugCategory: bug. Something is wrong. This is bad!E-mediumEffort: medium. Some knowledge of how hyper internal works would be useful.
Hyper will answer an HTTP/1.0 request as if it were an HTTP/1.1 request. This includes the following violations:
Hyper server sets the response version to HTTP/1.1 even for HTTP/1.0 requests
Hyper server will enter into keep-alive mode without sending Connection: keep-alive to the client
Hyper server will use Transfer-Encoding: chunked regardless of client version
All of these items violate backwards compatilbility. An HTTP/1.1 server should be backwards compatible. Failing that I suggest that Hyper instead drops the connection, but I hope backwards compatibility could be achieved without too much trouble.
For keep-alive: HTTP/1.0 has support for parts of the keep-alive functionality, but for backwards compatibility it is sufficient to completely disable it when the request is of version 1.0.
For chunked transfer encoding: This is fundamentally not available in HTTP/1.0. However, streaming responses are possible by sending the body directly and terminating the TCP connection when completed. (This is a hopeless design, which is how we came to HTTP/1.1 in the first place)
Do we still need HTTP/1.0 compatibility? I stumbled onto this problem when benchmarking my server with apachebench, which only supports HTTP/1.0. Nginx also surprisingly defaults to using version 1.0 when talking to backend servers as a reverse proxy, though it can be configured to use HTTP/1.1 (and maybe even 2 these days?)
Are there workarounds? It is possible to run the server behind a reverse proxy that is correctly backwards compatible with clients, but still uses HTTP/1.1 to communicate with the backends. Nginx is an example of this. (If you configure it correctly)
The text was updated successfully, but these errors were encountered:
Hey, thanks for filing this! It's true, hyper does ignore some things about how to deal with HTTP/1.0 peers. It would be nice to fix them.
Do we still need HTTP/1.0 compatibility?
I have wondered the same. I also haven't actually run into an HTTP/1.0 server or client myself.
Some support already exists, and it seems like a good idea to add the rest.
Keep-Alive: I had actually thought that this part at least was implemented correctly for 1.0 and 1.1. If a server sees a client talking 1.0, it won't assume keep-alive unless the client sent Connection: keep-alive. What part is incorrect?
Responding with the correct version would be a good, not too complicated, fix.
Checking the peer version and disabled chunked would be good too. I haven't read how 1.0 is supposed to handle messages without a length. Is it simply either Content-Length, or until EOF and thus keep-alive is disabled?
Thanks for getting back to me :) I'll try to clarify the rest:
Connection defaults to close in 1.0 and keep-alive in 1.1, so when the client requests keep-alive, the server has to include Connection: keep-alive in the response to verify support for this. (This is in contrast to 1.1, where both sides can assume keep-alive if nothing else is said) Hyper server is lacking this in the response. I haven't looked at the client, but I assume the converse error here? In any case, the correct behavior for the client is to ask for keep-alive and treat the connection mode as whatever the server responds, dependent on version:
The server responds with HTTP/1.0 and no Connection header: Treat the connection as non-pipelined, as if the server had said Connection: close.
The server responds with HTTP/1.1 (or 1.x, where x >= 1) and no Connection header: Treat the connection as pipelined, as if the server had said Connection: keep-alive.
If the server response includes a Connection header, regardless of HTTP version, respect this header.
I think you have understood correctly how to treat messages without a declared Content-Length in 1.0. Either you have Content-Length, or the body is sent and terminated by closing the connection. This means that if the server is planning on replying without a set Content-Length, it must avoid enabling Connection: keep-alive. This probably interacts with how a client would send the body in a POST or PUT request. Perhaps it is impossible to send a body without Content-Length to a 1.0 server? I'm not sure.
A-serverArea: server.C-bugCategory: bug. Something is wrong. This is bad!E-mediumEffort: medium. Some knowledge of how hyper internal works would be useful.
Hyper will answer an HTTP/1.0 request as if it were an HTTP/1.1 request. This includes the following violations:
HTTP/1.1
even forHTTP/1.0
requestsConnection: keep-alive
to the clientTransfer-Encoding: chunked
regardless of client versionAll of these items violate backwards compatilbility. An HTTP/1.1 server should be backwards compatible. Failing that I suggest that Hyper instead drops the connection, but I hope backwards compatibility could be achieved without too much trouble.
For keep-alive: HTTP/1.0 has support for parts of the keep-alive functionality, but for backwards compatibility it is sufficient to completely disable it when the request is of version 1.0.
For chunked transfer encoding: This is fundamentally not available in HTTP/1.0. However, streaming responses are possible by sending the body directly and terminating the TCP connection when completed. (This is a hopeless design, which is how we came to HTTP/1.1 in the first place)
Do we still need HTTP/1.0 compatibility? I stumbled onto this problem when benchmarking my server with apachebench, which only supports HTTP/1.0. Nginx also surprisingly defaults to using version 1.0 when talking to backend servers as a reverse proxy, though it can be configured to use HTTP/1.1 (and maybe even 2 these days?)
Are there workarounds? It is possible to run the server behind a reverse proxy that is correctly backwards compatible with clients, but still uses HTTP/1.1 to communicate with the backends. Nginx is an example of this. (If you configure it correctly)
The text was updated successfully, but these errors were encountered: