diff --git a/CHANGES/4630.bugfix b/CHANGES/4630.bugfix new file mode 100644 index 00000000000..65d783be049 --- /dev/null +++ b/CHANGES/4630.bugfix @@ -0,0 +1 @@ +Handle the last CRLF correctly even if it is received via separate TCP segment. diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index b40c107f6cd..f95ef97f8bd 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -153,6 +153,7 @@ Julia Tsemusheva Julien Duponchelle Jungkook Park Junjie Tao +Junyeong Jeong Justas Trimailovas Justin Foo Justin Turner Arthur diff --git a/aiohttp/http_parser.py b/aiohttp/http_parser.py index 64e4b30c22e..b76ce094014 100644 --- a/aiohttp/http_parser.py +++ b/aiohttp/http_parser.py @@ -668,12 +668,26 @@ def feed_data(self, # we should get another \r\n otherwise # trailers needs to be skiped until \r\n\r\n if self._chunk == ChunkState.PARSE_MAYBE_TRAILERS: - if chunk[:2] == SEP: - # end of stream - self.payload.feed_eof() - return True, chunk[2:] + if len(chunk) >= 2: + if chunk[:2] == SEP: + # end of stream + self.payload.feed_eof() + return True, chunk[2:] + else: + self._chunk = ChunkState.PARSE_TRAILERS else: - self._chunk = ChunkState.PARSE_TRAILERS + # Both CR and LF, or only LF may not be received + # yet. It is expected that CRLF or LF will be shown at + # the very first byte next time, otherwise trailers + # should come. + # The last CRLF which marks the end of response + # might not be contained in the same TCP segment which + # delivered the size indicator. + if not chunk or chunk[:1] == SEP[:1]: + self._chunk_tail = chunk + return False, b'' + else: + self._chunk = ChunkState.PARSE_TRAILERS # read and discard trailer up to the CRLF terminator if self._chunk == ChunkState.PARSE_TRAILERS: