@@ -2,7 +2,7 @@ HTTPX's `Client` also accepts a `transport` argument. This argument allows you
22to provide a custom Transport object that will be used to perform the actual
33sending of the requests.
44
5- ## HTTPTransport
5+ ## HTTP Transport
66
77For some advanced configuration you might need to instantiate a transport
88class directly, and pass it to the client instance. One example is the
@@ -83,7 +83,7 @@ with httpx.Client(transport=transport, base_url="http://testserver") as client:
8383 ...
8484```
8585
86- ## ASGITransport
86+ ## ASGI Transport
8787
8888You can configure an ` httpx ` client to call directly into an async Python web application using the ASGI protocol.
8989
@@ -148,7 +148,7 @@ However it is suggested to use `LifespanManager` from [asgi-lifespan](https://gi
148148
149149## Custom transports
150150
151- A transport instance must implement the low-level Transport API, which deals
151+ A transport instance must implement the low-level Transport API which deals
152152with sending a single request, and returning a response. You should either
153153subclass ` httpx.BaseTransport ` to implement a transport to use with ` Client ` ,
154154or subclass ` httpx.AsyncBaseTransport ` to implement a transport to
@@ -166,28 +166,81 @@ A complete example of a custom transport implementation would be:
166166import json
167167import httpx
168168
169-
170169class HelloWorldTransport (httpx .BaseTransport ):
171170 """
172171 A mock transport that always returns a JSON "Hello, world!" response.
173172 """
174173
175174 def handle_request (self , request ):
176- message = {" text" : " Hello, world!" }
177- content = json.dumps(message).encode(" utf-8" )
178- stream = httpx.ByteStream(content)
179- headers = [(b " content-type" , b " application/json" )]
180- return httpx.Response(200 , headers = headers, stream = stream)
175+ return httpx.Response(200 , json = {" text" : " Hello, world!" })
181176```
182177
183- Which we can use in the same way:
178+ Or this example, which uses a custom transport and ` httpx.Mounts ` to always redirect ` http:// ` requests.
184179
185- ``` pycon
186- >>> import httpx
187- >>> client = httpx.Client(transport = HelloWorldTransport())
188- >>> response = client.get(" https://example.org/" )
189- >>> response.json()
190- {"text": "Hello, world!"}
180+ ``` python
181+ class HTTPSRedirect (httpx .BaseTransport ):
182+ """
183+ A transport that always redirects to HTTPS.
184+ """
185+ def handle_request (self , request ):
186+ url = request.url.copy_with(scheme = " https" )
187+ return httpx.Response(303 , headers = {" Location" : str (url)})
188+
189+ # A client where any `http` requests are always redirected to `https`
190+ transport = httpx.Mounts({
191+ ' http://' : HTTPSRedirect()
192+ ' https://' : httpx.HTTPTransport()
193+ })
194+ client = httpx.Client(transport = transport)
195+ ```
196+
197+ A useful pattern here is custom transport classes that wrap the default HTTP implementation. For example...
198+
199+ ``` python
200+ class DebuggingTransport (httpx .BaseTransport ):
201+ def __init__ (self , ** kwargs ):
202+ self ._wrapper = httpx.HTTPTransport(** kwargs)
203+
204+ def handle_request (self , request ):
205+ print (f " >>> { request} " )
206+ response = self ._wrapper.handle_request(request)
207+ print (f " <<< { response} " )
208+ return response
209+
210+ def close (self ):
211+ self ._wrapper.close()
212+
213+ transport = DebuggingTransport()
214+ client = httpx.Client(transport = transport)
215+ ```
216+
217+ Here's another case, where we're using a round-robin across a number of different proxies...
218+
219+ ``` python
220+ class ProxyRoundRobin (httpx .BaseTransport ):
221+ def __init__ (self , proxies , ** kwargs ):
222+ self ._transports = [
223+ httpx.HTTPTransport(proxy = proxy, ** kwargs)
224+ for proxy in proxies
225+ ]
226+ self ._idx = 0
227+
228+ def handle_request (self , request ):
229+ transport = self ._transports[self ._idx]
230+ self ._idx = (self ._idx + 1 ) % len (self ._transports)
231+ return transport.handle_request(request)
232+
233+ def close (self ):
234+ for transport in self ._transports:
235+ transport.close()
236+
237+ proxies = [
238+ httpx.Proxy(" http://127.0.0.1:8081" ),
239+ httpx.Proxy(" http://127.0.0.1:8082" ),
240+ httpx.Proxy(" http://127.0.0.1:8083" ),
241+ ]
242+ transport = ProxyRoundRobin(proxies = proxies)
243+ client = httpx.Client(transport = transport)
191244```
192245
193246## Mock transports
0 commit comments