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
{{ message }}
Repository navigation
Bad BaseHTTPRequestHandler response when using HTTP/0.9 #70765
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=Nonecreated_at=<Date2016-03-17.07:42:36.782>labels= ['type-bug', 'library']
title='Bad BaseHTTPRequestHandler response when using HTTP/0.9'updated_at=<Date2016-10-29.11:19:59.882>user='https://github.com/zhangyangyu'
BaseHTTPRequestHandler in http.server supports HTTP/0.9. But the response for HTTP/0.9 request is implemented wrong.
Response of HTTP/0.9 request returns message body directly without status line and headers. But if you inherit BaseHTTPRequestHandler and set the default_request_version to "HTTP/1.x", then self.request_version can never be "HTTP/0.9" since in the https://hg.python.org/cpython/file/tip/Lib/http/server.py#l315 branch it does not set version to "HTTP/0.9" and then always sends the status line and headers back.
A trivial patch can fix this problem that set version to "HTTP/0.9" in the branch. But this will cause some failure in tests. The tests in test_httpservers use http.client.HTTPConnection to send and receive HTTP message. But since 3.4, HTTPConnection doesn't support HTTP/0.9-style simple responses. We can use it to test HTTP/0.9 connection if the server is implemented in the right way.
And since http.client.HTTPConnection has dropped the support for HTTP/0.9, is it reasonable to drop the support in http.server too?
As I understand it, you are saying if you override the undocumented (but publicly-named) default_request_version attribute, HTTP 0.9 requests no longer work.
I suspect it is even broken by default. My understanding is with HTTP 0.9 you should be able to send b"GET <path>\r\n" and get a response, but Python’s server will deadlock waiting for a second blank line or EOF. It looks like this deadlock has been there since ~forever (1995).
See bpo-10721 which already proposes to remove 0.9 server support. I would be weakly in favour of this (or more strongly if someone can prove my theory that the current support is broken).
I think you are right. Simply run http.server.test() and then telnet to send "GET /", the client hangs. Or add a timeout to BaseHTTPRequestHandler, you can see the timeout error on server output.
Since my last comment, I have become more confident that Python’s request parsing never supported proper HTTP 0.9. So I would prefer to remove it in the next version of Python, and not bother fixing Xiang’s bug in existing versions (unless someone offers a practical reason to fix it).
For the record, this patch is what a fix might look like.
There was a simple fix which consisted in not parsing the rest of the request as there shouldn't be headers. But deprecating the support would also be fine (there is a lot of code that is still assuming HTTP/0.9 but it's actually never tested because we never get past parse_request where it hangs because it expects some headers).
Note that HTTPConnection has no support for HTTP/0.9 so a client would need to use raw sockets.
Activity
zhangyangyu commentedon Mar 17, 2016
BaseHTTPRequestHandler in http.server supports HTTP/0.9. But the response for HTTP/0.9 request is implemented wrong.
Response of HTTP/0.9 request returns message body directly without status line and headers. But if you inherit BaseHTTPRequestHandler and set the default_request_version to "HTTP/1.x", then self.request_version can never be "HTTP/0.9" since in the https://hg.python.org/cpython/file/tip/Lib/http/server.py#l315 branch it does not set version to "HTTP/0.9" and then always sends the status line and headers back.
A trivial patch can fix this problem that set version to "HTTP/0.9" in the branch. But this will cause some failure in tests. The tests in test_httpservers use http.client.HTTPConnection to send and receive HTTP message. But since 3.4, HTTPConnection doesn't support HTTP/0.9-style simple responses. We can use it to test HTTP/0.9 connection if the server is implemented in the right way.
And since http.client.HTTPConnection has dropped the support for HTTP/0.9, is it reasonable to drop the support in http.server too?
zhangyangyu commentedon Mar 17, 2016
can should be can not.
And not only HTTPConnection, support for HTTP/0.9 seems to have been totally abandoned since Python3.4 in http.client.
vadmium commentedon Mar 18, 2016
As I understand it, you are saying if you override the undocumented (but publicly-named) default_request_version attribute, HTTP 0.9 requests no longer work.
I suspect it is even broken by default. My understanding is with HTTP 0.9 you should be able to send b"GET <path>\r\n" and get a response, but Python’s server will deadlock waiting for a second blank line or EOF. It looks like this deadlock has been there since ~forever (1995).
See bpo-10721 which already proposes to remove 0.9 server support. I would be weakly in favour of this (or more strongly if someone can prove my theory that the current support is broken).
zhangyangyu commentedon Mar 18, 2016
I think you are right. Simply run http.server.test() and then telnet to send "GET /", the client hangs. Or add a timeout to BaseHTTPRequestHandler, you can see the timeout error on server output.
vadmium commentedon Oct 29, 2016
Since my last comment, I have become more confident that Python’s request parsing never supported proper HTTP 0.9. So I would prefer to remove it in the next version of Python, and not bother fixing Xiang’s bug in existing versions (unless someone offers a practical reason to fix it).
For the record, this patch is what a fix might look like.
zhangyangyu commentedon Oct 29, 2016
+1. In rfc7230, "The expectation to support HTTP/0.9 requests has been removed".
BaseHTTPRequestHandlerincorrectly expects headers from HTTP/0.9 requests #139492 as a duplicate of this issuepicnixz commentedon Oct 2, 2025
There was a simple fix which consisted in not parsing the rest of the request as there shouldn't be headers. But deprecating the support would also be fine (there is a lot of code that is still assuming HTTP/0.9 but it's actually never tested because we never get past
parse_requestwhere it hangs because it expects some headers).Note that HTTPConnection has no support for HTTP/0.9 so a client would need to use raw sockets.
gh-70765: avoid waiting for HTTP headers when parsing HTTP/0.9 reques…
pythongh-70765: avoid waiting for HTTP headers when parsing HTTP/0.9 …
[3.13] pythongh-70765: avoid waiting for HTTP headers when parsing HT…
test_httpserversis flaky on macOS #139611 as a duplicate of this issue1 remaining item
pythongh-70765: avoid waiting for HTTP headers when parsing HTTP/0.9 …
[3.13] pythongh-70765: avoid waiting for HTTP headers when parsing HT…
[3.14] pythongh-70765: avoid waiting for HTTP headers when parsing HT…
[3.14] pythongh-70765: avoid waiting for HTTP headers when parsing HT…
[3.13] pythongh-70765: avoid waiting for HTTP headers when parsing HT…
pythongh-70765: avoid waiting for HTTP headers when parsing HTTP/0.9 …
pythongh-70765: fix an HTTP/0.9 flaky test post pythonGH-139514 (pyth…
[3.13] gh-70765: avoid waiting for HTTP headers when parsing HTTP/0.9…
[3.14] gh-70765: avoid waiting for HTTP headers when parsing HTTP/0.9…
gh-70765: Remove unnecessary extra backtick from Changelog entry (#14…
pythongh-70765: Remove unnecessary extra backtick from Changelog entry (
pythongh-70765: Remove unnecessary extra backtick from Changelog entry (
[3.14] gh-70765: Remove unnecessary extra backtick from Changelog ent…
[3.13] gh-70765: Remove unnecessary extra backtick from Changelog ent…