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
From RFC 7230 Section 3.5 (Message Parsing Robustness):
Although the line terminator for the start-line and header fields is the sequence CRLF, a recipient MAY recognize a single LF as a line terminator and ignore any preceding CR.
This suggests that allowing simply \n and not \r is acceptable, which I think is probably the way to go. While technically just '\rmight happen, I really don't think it's worth it in terms of compat cost.
This suggests that allowing simply \n and not \r is acceptable, which I think is probably the way to go. While technically just '\r might happen, I really don't think it's worth it in terms of compat cost.
I'm not sure it makes much difference in terms of implementation simplicity, because h11's trick for simple fast HTTP header parsing is use bytearray.find("\r\n\r\n"), so we'd still have to duplicate this check to look for \n\n at least.
BTW, I assume that servers that screw this up for headers also screw it up for chunked encoding?
@njsmith No need to duplicate the check: better to swap to a fairly simple regex. Either way you desperately need to avoid having too much cleverness here in Python, because each time you come back into Python code to process the bytestream you slow down a load on CPython (which for better or worse is what users will use to judge your perf).
@Lukasa: yeah, agreed that re.search is probably the way to go, and that's why we're already doing header framing handling in a single call into the C runtime... but my point is that if we were doing line-by-line scanning then searching for \n would be just as easy as searching for \r\n (and would handle \r\n implicitly)... but since we're scanning for the whole headers at once then we need to do some sort of explicit handling of both \r\n\r\n and \n\n, and once you have two cases then adding a third probably isn't that hard.
(Searching the web for that .NET error message -- "The server committed a protocol violation. Section=ResponseHeader Detail=CR must be followed by LF" -- is a good way to find other examples of broken servers. Apparently .NET is the one HTTP client that really enforces this. The error message is emitted any time a .NET client sees a CR without an LF, or an LF without a CR, unless its been configured in this horrible global be-sloppy-and-insecure more.)
I'm not 100% convinced we need to accept mixed headers, but it would probably be good to at least error out early if we see lone \r or \n -- right now if we'll just block forever waiting for \r\n\r\n, which might never arrive.
OTOH it looks like for chunked encoding, at least http.client and go both require \r\n only, no exceptions. So we probably don't need to worry about that. I guess server implementors who are too lazy to implement headers properly are also too lazy to implement chunked encoding.
I'm sorry for bumping up so old ticket, but not so far ago I stuck with some problem in httpx (encode/httpx#1378) which is caused by an old webserver (there is an assumption that it's Boa web server), which splits Headers and Body with "\n".
As the server is a bit obsolete, and used in embedded development, it might be impossible to update it. May be, operating with such systems, we might be a bit more tolerant.
It's definitely possible and we should do it. Just, no one has written the code yet :-)
It'll be a bit hacky because of how our buffering works. Right now we search for \r\n\r\n and track how much of the string we've searched. For this I think the fastest approach will be to use a regex to search for \n\r?\n, and also track how much we've searched.
Activity
njsmith commentedon Jun 4, 2016
(NB I'm probably not going to work on this any time soon)
njsmith commentedon Jun 4, 2016
CC: @durin42 since it's his fault I know about this
Lukasa commentedon Jun 4, 2016
From RFC 7230 Section 3.5 (Message Parsing Robustness):
This suggests that allowing simply
\nand not\ris acceptable, which I think is probably the way to go. While technically just'\rmight happen, I really don't think it's worth it in terms of compat cost.durin42 commentedon Jun 4, 2016
Sadly, I’ve seen \r without \n in the wild. :(
Lukasa commentedon Jun 4, 2016
Oh, so have I. But I am a strong advocate of telling implementations that haven't read RFCs to go take a long walk off a short pier.
njsmith commentedon Jun 4, 2016
I'm not sure it makes much difference in terms of implementation simplicity, because h11's trick for simple fast HTTP header parsing is use
bytearray.find("\r\n\r\n"), so we'd still have to duplicate this check to look for\n\nat least.BTW, I assume that servers that screw this up for headers also screw it up for chunked encoding?
Lukasa commentedon Jun 4, 2016
@njsmith No need to duplicate the check: better to swap to a fairly simple regex. Either way you desperately need to avoid having too much cleverness here in Python, because each time you come back into Python code to process the bytestream you slow down a load on CPython (which for better or worse is what users will use to judge your perf).
njsmith commentedon Jun 4, 2016
@Lukasa: yeah, agreed that
re.searchis probably the way to go, and that's why we're already doing header framing handling in a single call into the C runtime... but my point is that if we were doing line-by-line scanning then searching for\nwould be just as easy as searching for\r\n(and would handle\r\nimplicitly)... but since we're scanning for the whole headers at once then we need to do some sort of explicit handling of both\r\n\r\nand\n\n, and once you have two cases then adding a third probably isn't that hard.njsmith commentedon Dec 8, 2016
More notes on this for future reference:
It looks like most extant parsers accept
\nor\r\non a line-by-line basis (i.e., even mixed headers are accepted). Here's an example of a broken API that returned a mix of both: http://mehdi.me/a-tale-of-debugging-the-linkedin-api-net-and-http-protocol-violations/(Searching the web for that .NET error message -- "The server committed a protocol violation. Section=ResponseHeader Detail=CR must be followed by LF" -- is a good way to find other examples of broken servers. Apparently .NET is the one HTTP client that really enforces this. The error message is emitted any time a .NET client sees a CR without an LF, or an LF without a CR, unless its been configured in this horrible global be-sloppy-and-insecure more.)
I'm not 100% convinced we need to accept mixed headers, but it would probably be good to at least error out early if we see lone
\ror\n-- right now if we'll just block forever waiting for\r\n\r\n, which might never arrive.OTOH it looks like for chunked encoding, at least
http.clientand go both require\r\nonly, no exceptions. So we probably don't need to worry about that. I guess server implementors who are too lazy to implement headers properly are also too lazy to implement chunked encoding.cdeler commentedon Nov 5, 2020
Hello @njsmith
Problem description
I'm sorry for bumping up so old ticket, but not so far ago I stuck with some problem in
httpx(encode/httpx#1378) which is caused by an old webserver (there is an assumption that it's Boa web server), which splitsHeadersandBodywith"\n".As the server is a bit obsolete, and used in embedded development, it might be impossible to update it. May be, operating with such systems, we might be a bit more tolerant.
Some extra details:
Server sends a Response like that:
hexdump of the response
More details you can find in encode/httpx#1378 and Kane610/axis#55
As you can see, the headers section ends with:
00000100 74 2f 70 6c 61 69 6e 0a 0a t/plain. .i.e. with\n\nThe question
Do you think, if it's possible to make
h11less strict and to allowh11accepting the LF as a response header/body delimiter?njsmith commentedon Nov 5, 2020
It's definitely possible and we should do it. Just, no one has written the code yet :-)
It'll be a bit hacky because of how our buffering works. Right now we search for
\r\n\r\nand track how much of the string we've searched. For this I think the fastest approach will be to use a regex to search for\n\r?\n, and also track how much we've searched.cdeler commentedon Nov 10, 2020
Hello @njsmith ,
Is it possible to ask you to review the PR associated with this ticket (#115)?
h11: Autospec creation for update from version 0.11.0 to version 0.12.0