Httpx: Supporting `Response(content=..., text=..., html=..., json=...)`

Created on 27 Aug 2020  ·  3Comments  ·  Source: encode/httpx

We’d like to support instantiating Response instances directly.

One really good example of why we might want to do that is for unit testing custom auth classes - https://github.com/encode/httpx/pull/1217#issuecomment-681825882

Currently Response instances are only ever created by the client itself, and...

  • Have a mandatory request=... parameter.
  • Have a mandatory status_code parameter.

The first things we should do here are:

  • Make the request parameter become optional. Have a .request property that returns a Request instance or raises a RuntimeError if the instance is not set. Have a property setter for the .request property.
  • Make the status code be enforced as kwarg-only, and make it optional, with a default of 200.

Once we’ve done those things we should add support for setting the content of a response, using content=..., text=..., html=..., json=... parameters, which mirror the request parameters of data=..., files=..., json=..., but differ because HTTP responses use different content types to HTTP requests.

The encode(...) method in content_streams.py would become encode_request_body(data=..., files=..., json=..., boundary=...), and would be mirrored by a encode_response_body(content=..., text=..., html=..., json=...) method, which would use the following content streams:

  • content - Support either bytes or byte iterator/aiterators. Setting Content-Length or Transfer-Encoding: chunked
  • text - Set Content-Type: text/plain; charset=“utf-8”, and a Content-Length header.
  • html - Set Content-Type: text/html; charset=“utf-8” and a Content-Length header.
  • json - Set Content-Type: application/json and a Content-Length header.

We can tie in an encoding=... argument too, but let’s talk that through as a follow up.

What this would then all give us is the ability to create responses like so...

response = httpx.Response(json={“hello”: “world”})
response = httpx.Response(html=“<body><h1>hello, world</h1></body>”})
response = httpx.Response(text=“Not found”, status_code=404)
response = httpx.Response(content=b’...’, headers=...)

Somewhat refs #1091

enhancement

Most helpful comment

If any contributors want to take a go at this I'd suggest approaching it in parts...

  • Issue a PR for making the request=... parameter not mandatory.
  • Issue a PR making status_code a keyword-only argument, and defaulting it to 200.
  • Issue a PR with the response body encoding handling (more complex than the other two.)

All 3 comments

If any contributors want to take a go at this I'd suggest approaching it in parts...

  • Issue a PR for making the request=... parameter not mandatory.
  • Issue a PR making status_code a keyword-only argument, and defaulting it to 200.
  • Issue a PR with the response body encoding handling (more complex than the other two.)

The issue is quite detailed thanks for that. 😄 I don't have much experience with httpx but would love to give it a try.

Great. Definitely treat each of those items in isolation as separate PRs. 😀

Was this page helpful?
0 / 5 - 0 ratings