Skip to content

Commit

Permalink
update docstring/docs for transport using request/response models (#2070
Browse files Browse the repository at this point in the history
)

* update docstring/docs for transport based on pull #1840

* Update httpx/_transports/base.py

* lint'd

Co-authored-by: Tom Christie <tom@tomchristie.com>
  • Loading branch information
toppk and tomchristie committed Feb 8, 2022
1 parent 420911b commit 4f8068a
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 55 deletions.
11 changes: 4 additions & 7 deletions docs/advanced.md
Expand Up @@ -1051,10 +1051,8 @@ subclass `httpx.BaseTransport` to implement a transport to use with `Client`,
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.
Expand All @@ -1071,13 +1069,12 @@ class HelloWorldTransport(httpx.BaseTransport):
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:
Expand Down
65 changes: 17 additions & 48 deletions httpx/_transports/base.py
Expand Up @@ -23,63 +23,32 @@ def handle_request(self, request: Request) -> Response:
"""
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."
Expand Down

0 comments on commit 4f8068a

Please sign in to comment.