httpx: Graceful handling of 204 responses that incorrectly a include non-zero Content-Length.
Checklist
- The bug is reproducible against the latest release and/or
master. - There are no similar issues or pull requests to fix it yet.
Describe the bug
HTTPX Session encounters parsing error (RemoteProtocolError: malformed data) when an endpoint returns content when status code is 204 (HTTP No Content). Other Python http clients handle this scenario… I’m not sure if httpx should actually handle this case, since this is a weird case, but maybe it’s best to handle it?
To reproduce
setup FastAPI server with this code:
from typing import Optional
from fastapi import FastAPI
from starlette.status import HTTP_204_NO_CONTENT
app = FastAPI()
@app.get("/", status_code=HTTP_204_NO_CONTENT)
def read_root():
print("d")
Run it using uvicorn. In another terminal run the following snippet:
import httpx
client = httpx.Client()
client.get('http://localhost:8000/")
# The second one will get an error
client.get('http://localhost:8000/")
Expected behavior
No errors?
Actual behavior
malformed data
Debugging material
~/.pyenv/versions/3.8.2/lib/python3.8/site-packages/httpx/_client.py in get(self, url, params, headers, cookies, auth, allow_redirects, timeout)
905 **Parameters**: See `httpx.request`.
906 """
--> 907 return self.request(
908 "GET",
909 url,
~/.pyenv/versions/3.8.2/lib/python3.8/site-packages/httpx/_client.py in request(self, method, url, content, data, files, json, params, headers, cookies, auth, allow_redirects, timeout)
731 cookies=cookies,
732 )
--> 733 return self.send(
734 request, auth=auth, allow_redirects=allow_redirects, timeout=timeout
735 )
~/.pyenv/versions/3.8.2/lib/python3.8/site-packages/httpx/_client.py in send(self, request, stream, auth, allow_redirects, timeout)
765 auth = self._build_request_auth(request, auth)
766
--> 767 response = self._send_handling_auth(
768 request,
769 auth=auth,
~/.pyenv/versions/3.8.2/lib/python3.8/site-packages/httpx/_client.py in _send_handling_auth(self, request, auth, timeout, allow_redirects, history)
803
804 while True:
--> 805 response = self._send_handling_redirects(
806 request,
807 timeout=timeout,
~/.pyenv/versions/3.8.2/lib/python3.8/site-packages/httpx/_client.py in _send_handling_redirects(self, request, timeout, allow_redirects, history)
835 )
836
--> 837 response = self._send_single_request(request, timeout)
838 response.history = list(history)
839
~/.pyenv/versions/3.8.2/lib/python3.8/site-packages/httpx/_client.py in _send_single_request(self, request, timeout)
859
860 with map_exceptions(HTTPCORE_EXC_MAP, request=request):
--> 861 (status_code, headers, stream, ext) = transport.request(
862 request.method.encode(),
863 request.url.raw,
~/.pyenv/versions/3.8.2/lib/python3.8/contextlib.py in __exit__(self, type, value, traceback)
129 value = type()
130 try:
--> 131 self.gen.throw(type, value, traceback)
132 except StopIteration as exc:
133 # Suppress StopIteration *unless* it's the same exception that
~/.pyenv/versions/3.8.2/lib/python3.8/site-packages/httpx/_exceptions.py in map_exceptions(mapping, **kwargs)
341
342 message = str(exc)
--> 343 raise mapped_exc(message, **kwargs) from exc # type: ignore
344
345
RemoteProtocolError: malformed data
Environment
- OS: macOS
- Python version: 3.8.2
- HTTPX version: 0.16.1
- Async environment: Both (asyncio, blocking)
- HTTP proxy: no
- Custom certificates: no
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 1
- Comments: 16 (9 by maintainers)
Yep, FastAPI was at fault. This was solved in https://github.com/tiangolo/fastapi/pull/5145, available since FastAPI
0.79.0. 🎉