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
write_any_response not sending optional causes failure on Samsung TV #73
I'm trying to work on an app that communicates with my Samsung TV. After some digging I figured out that the missing status text causes it to not work.
def write_any_response(response, write):
if response.http_version != b"1.1":
raise LocalProtocolError("I only send HTTP/1.1")
status_bytes = str(response.status_code).encode("ascii")
# We don't bother sending ascii status messages like "OK"; they're
# optional and ignored by the protocol. (But the space after the numeric
# status code is mandatory.)
#
# XX FIXME: could at least make an effort to pull out the status message
# from stdlib's http.HTTPStatus table. Or maybe just steal their enums
# (either by import or copy/paste). We already accept them as status codes
# since they're of type IntEnum < int.
write(bytesmod(b"HTTP/1.1 %s %s\r\n", (status_bytes, response.reason)))
write_headers(response.headers, write)
Seeing as how there is a FIXME here already. Would it be possible to get the following added?
from http import HTTPStatus
response.reason = HTTPStatus(response.status_code).name.encode('ascii')
I'm using Quart, which uses h11. The app I'm working on is not quite ready to be published. I've got it working with Flask, but the tv won't respond to the Quart version unless I populate the response.reason. By your comment, I'm assuming the response.reason should be populated before it gets to write_any_response().
I see asgi_send() being called with the message, but then it builds a new response using only the status. self.send(h11.Response(status_code=self.response['status'], headers=headers))
Where is the correct place for me to supply the reason?
The quick fix would be to pass the reason phrase into the h11.Response constructor, like: h11.Response(status_code=self.response['status'], headers=headers, reason="blah blah")
Out of curiosity, does your TV require a specific reason phrase, or does it just insist that it be non-empty?
Given that this is breaking things (wtf is wrong with you, samsung TV), maybe we should also start defaulting the reason inside h11 when it's not specified. Probably the way to do this would be in the Reponse/InformationalResponse constructor, if the reason argument isn't passed, set a default based on the status code.
I finally got around to posting the app I mentioned that has the problem on my tv. https://github.com/shaolo1/VideoServer. I've temporarily monkey patched the h11 issue to get it working.
Hi! Triaging older issues — I think this one can be closed: h11 already sends whatever reason text the caller provides, which matches what the maintainer pointed out in the first reply on this thread.
Evidence:
h11/_writers.py:44-59 — write_any_response emits b"HTTP/1.1 %s %s\r\n" % (status_bytes, response.reason); the reason bytes are written verbatim, the only out-of-date thing here is the comment ("we don't bother sending ascii status messages...") which no longer matches the code.
h11/_events.py:137-164 — Response.__init__ accepts a reason keyword (bytes or str) and stores it; passing reason=b"OK" is sufficient to send HTTP/1.1 200 OK.
Local reproducer against current master (commit 62c5068):
The Samsung-TV workaround in the linked VideoServer project (passing an explicit reason) is exactly the supported way. If having h11 auto-fill a default reason from http.HTTPStatus is still wanted, that feels like a separate feature request (matching the # XX FIXME note in _writers.py:54).
If I'm wrong about the reproduction or there's still a regression I missed, point me at it and I'll dig further. Otherwise would you mind closing this out?
Disclosure: I drafted this comment with help from Claude Code while triaging stale issues; the file references and reproducer above were verified manually against current master.
Activity
njsmith commentedon Aug 20, 2018
That comment is out of date... As you can see from the code, h11 does send whatever "reason" text the user gives it.
Can you give more details on how you're using h11, and how you concluded that Samsung's http implementation is broken?
shaolo1 commentedon Aug 20, 2018
I'm using Quart, which uses h11. The app I'm working on is not quite ready to be published. I've got it working with Flask, but the tv won't respond to the Quart version unless I populate the response.reason. By your comment, I'm assuming the response.reason should be populated before it gets to write_any_response().
I see asgi_send() being called with the message, but then it builds a new response using only the status.
self.send(h11.Response(status_code=self.response['status'], headers=headers))Where is the correct place for me to supply the reason?
njsmith commentedon Aug 20, 2018
The quick fix would be to pass the reason phrase into the
h11.Responseconstructor, like:h11.Response(status_code=self.response['status'], headers=headers, reason="blah blah")Out of curiosity, does your TV require a specific reason phrase, or does it just insist that it be non-empty?
Given that this is breaking things (wtf is wrong with you, samsung TV), maybe we should also start defaulting the
reasoninside h11 when it's not specified. Probably the way to do this would be in theReponse/InformationalResponseconstructor, if thereasonargument isn't passed, set a default based on the status code.shaolo1 commentedon Aug 20, 2018
Interestingly enough its completely happy with b'HTTP/1.1 200 foo\r\n' or b'HTTP/1.1 206 foo\r\n'
njsmith commentedon Aug 21, 2018
Heh. Well, I guess that's another option: if
reasonisn't given, default tofoo.(I'm joking!)
shaolo1 commentedon Aug 22, 2018
I finally got around to posting the app I mentioned that has the problem on my tv. https://github.com/shaolo1/VideoServer. I've temporarily monkey patched the h11 issue to get it working.
jbbqqf commentedon May 22, 2026
Hi! Triaging older issues — I think this one can be closed: h11 already sends whatever
reasontext the caller provides, which matches what the maintainer pointed out in the first reply on this thread.Evidence:
h11/_writers.py:44-59—write_any_responseemitsb"HTTP/1.1 %s %s\r\n" % (status_bytes, response.reason); thereasonbytes are written verbatim, the only out-of-date thing here is the comment ("we don't bother sending ascii status messages...") which no longer matches the code.h11/_events.py:137-164—Response.__init__accepts areasonkeyword (bytes or str) and stores it; passingreason=b"OK"is sufficient to sendHTTP/1.1 200 OK.master(commit62c5068):The Samsung-TV workaround in the linked VideoServer project (passing an explicit
reason) is exactly the supported way. If having h11 auto-fill a default reason fromhttp.HTTPStatusis still wanted, that feels like a separate feature request (matching the# XX FIXMEnote in_writers.py:54).If I'm wrong about the reproduction or there's still a regression I missed, point me at it and I'll dig further. Otherwise would you mind closing this out?
Disclosure: I drafted this comment with help from Claude Code while triaging stale issues; the file references and reproducer above were verified manually against current
master.