or subclass `httpx.AsyncBaseTransport` to implement a transport to
use with `AsyncClient`.
-At the layer of the transport API we're using plain primitives.
-No `Request` or `Response` models, no fancy `URL` or `Header` handling.
-This strict point of cut-off provides a clear design separation between the
-HTTPX API, and the low-level network handling.
+At the layer of the transport API we're using the familiar `Request` and
+`Response` models.
See the `handle_request` and `handle_async_request` docstrings for more details
on the specifics of the Transport API.
A mock transport that always returns a JSON "Hello, world!" response.
"""
- def handle_request(self, method, url, headers, stream, extensions):
+ def handle_request(self, request):
message = {"text": "Hello, world!"}
content = json.dumps(message).encode("utf-8")
stream = httpx.ByteStream(content)
headers = [(b"content-type", b"application/json")]
- extensions = {}
- return 200, headers, stream, extensions
+ return httpx.Response(200, headers=headers, stream=stream)
```
Which we can use in the same way:
"""
Send a single HTTP request and return a response.
- At this layer of API we're simply using plain primitives. No `Request` or
- `Response` models, no fancy `URL` or `Header` handling. This strict point
- of cut-off provides a clear design separation between the HTTPX API,
- and the low-level network handling.
-
Developers shouldn't typically ever need to call into this API directly,
since the Client class provides all the higher level user-facing API
niceties.
- In order to properly release any network resources, the response stream
- should *either* be consumed immediately, with a call to `stream.read()`,
- or else the `handle_request` call should be followed with a try/finally
- block to ensuring the stream is always closed.
+ In order to properly release any network resources, the response
+ stream should *either* be consumed immediately, with a call to
+ `response.stream.read()`, or else the `handle_request` call should
+ be followed with a try/finally block to ensuring the stream is
+ always closed.
Example usage:
with httpx.HTTPTransport() as transport:
- status_code, headers, stream, extensions = transport.handle_request(
- method=b'GET',
- url=(b'https', b'www.example.com', 443, b'/'),
- headers=[(b'Host', b'www.example.com')],
- stream=[],
- extensions={}
+ req = httpx.Request(
+ method=b"GET",
+ url=(b"https", b"www.example.com", 443, b"/"),
+ headers=[(b"Host", b"www.example.com")],
)
- body = stream.read()
- print(status_code, headers, body)
-
- Arguments:
-
- method: The request method as bytes. Eg. b'GET'.
- url: The components of the request URL, as a tuple of `(scheme, host, port, target)`.
- The target will usually be the URL path, but also allows for alternative
- formulations, such as proxy requests which include the complete URL in
- the target portion of the HTTP request, or for "OPTIONS *" requests, which
- cannot be expressed in a URL string.
- headers: The request headers as a list of byte pairs.
- stream: The request body as a bytes iterator.
- extensions: An open ended dictionary, including optional extensions to the
- core request/response API. Keys may include:
- timeout: A dictionary of str:Optional[float] timeout values.
- May include values for 'connect', 'read', 'write', or 'pool'.
-
- Returns a tuple of:
-
- status_code: The response status code as an integer. Should be in the range 1xx-5xx.
- headers: The response headers as a list of byte pairs.
- stream: The response body as a bytes iterator.
- extensions: An open ended dictionary, including optional extensions to the
- core request/response API. Keys are plain strings, and may include:
- reason_phrase: The reason-phrase of the HTTP response, as bytes. Eg b'OK'.
- HTTP/2 onwards does not include a reason phrase on the wire.
- When no key is included, a default based on the status code may
- be used. An empty-string reason phrase should not be substituted
- for a default, as it indicates the server left the portion blank
- eg. the leading response bytes were b"HTTP/1.1 200 <CRLF>".
- http_version: The HTTP version, as bytes. Eg. b"HTTP/1.1".
- When no http_version key is included, HTTP/1.1 may be assumed.
+ resp = transport.handle_request(req)
+ body = resp.stream.read()
+ print(resp.status_code, resp.headers, body)
+
+
+ Takes a `Request` instance as the only argument.
+
+ Returns a `Response` instance.
"""
raise NotImplementedError(
"The 'handle_request' method must be implemented."