httpx 自定义传输

2022-07-26 15:35 更新

HTTPX ​Client ​也接受一个​transport​参数。此参数允许您提供将用于执行请求实际发送的自定义​transport​对象。

用法

对于某些高级配置,您可能需要直接实例化​transport​类,并将其传递到​client​实例。一个例子是​local_address​的配置只能通过此低级 API 获得。

>>> import httpx
>>> transport = httpx.HTTPTransport(local_address="0.0.0.0")
>>> client = httpx.Client(transport=transport)

也可以通过此接口重试连接。

>>> import httpx
>>> transport = httpx.HTTPTransport(retries=1)
>>> client = httpx.Client(transport=transport)

类似地,直接实例化​transport​提供了一个​uds​选项,用于通过Unix域套接字进行连接,该套接字仅可通过此低级API进行连接:

>>> import httpx
>>> # Connect to the Docker API via a Unix Socket.
>>> transport = httpx.HTTPTransport(uds="/var/run/docker.sock")
>>> client = httpx.Client(transport=transport)
>>> response = client.get("http://docker/info")
>>> response.json()
{"ID": "...", "Containers": 4, "Images": 74, ...}

urllib3 transport

这个公共gist提供了一个使用优秀的urllib3库的​transport​,并且可以与同步的​Client​一起使用...

>>> import httpx
>>> from urllib3_transport import URLLib3Transport
>>> client = httpx.Client(transport=URLLib3Transport())
>>> client.get("https://example.org")
<Response [200 OK]>

编写自定义transport

transport​实例必须实现低级 ​transport ​API,该API处理发送单个请求和返回响应。您应该创建​httpx​的子类。您应该使用子类​httpx.BaseTransport​来实现与​Client​一起使用的​transport​,或者使用子类​httpx.AsyncBaseTransport​来实现与​AsyncClient​一起使用的​transport​。

在​transport API ​层,我们使用的是熟悉的​Request​和​Response​模型。

有关​transport API ​细节的更多详细信息,请参阅 ​handle_request​和 ​handle_async_request​文档字符串。

自定义​transport​实现的完整示例如下:

import json
import httpx


class HelloWorldTransport(httpx.BaseTransport):
    """
    A mock transport that always returns a JSON "Hello, world!" response.
    """

    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")]
        return httpx.Response(200, headers=headers, stream=stream)

我们可以以相同的方式使用它:

>>> import httpx
>>> client = httpx.Client(transport=HelloWorldTransport())
>>> response = client.get("https://example.org/")
>>> response.json()
{"text": "Hello, world!"}

模拟transport

在测试期间,能够模拟​transport​并返回预先确定的响应,而不是发出实际的网络请求,这通常很有用。

httpx.MockTransport​类接受一个处理程序函数,该函数可用于将请求映射到预先确定的响应上:

def handler(request):
    return httpx.Response(200, json={"text": "Hello, world!"})


# Switch to a mock transport, if the TESTING environment variable is set.
if os.environ.get('TESTING', '').upper() == "TRUE":
    transport = httpx.MockTransport(handler)
else:
    transport = httpx.HTTPTransport()

client = httpx.Client(transport=transport)

对于更高级的用例,您可能需要查看第三方模拟库,例如RESPXpytest-httpx库

安装transport

您还可以针对给定的方案或域挂载transport,以控制传出请求应通过哪个transport进行路由,其样式与指定代理路由的样式相同

import httpx

class HTTPSRedirectTransport(httpx.BaseTransport):
    """
    A transport that always redirects to HTTPS.
    """

    def handle_request(self, method, url, headers, stream, extensions):
        scheme, host, port, path = url
        if port is None:
            location = b"https://%s%s" % (host, path)
        else:
            location = b"https://%s:%d%s" % (host, port, path)
        stream = httpx.ByteStream(b"")
        headers = [(b"location", location)]
        extensions = {}
        return 303, headers, stream, extensions


# A client where any `http` requests are always redirected to `https`
mounts = {'http://': HTTPSRedirectTransport()}
client = httpx.Client(mounts=mounts)

关于如何利用已安装的transport工具的其他一些草图...

正在禁用单个给定域上的 HTTP/2...

mounts = {
    "all://": httpx.HTTPTransport(http2=True),
    "all://*example.org": httpx.HTTPTransport()
}
client = httpx.Client(mounts=mounts)

模拟对给定域的请求:

# All requests to "example.org" should be mocked out.
# Other requests occur as usual.
def handler(request):
    return httpx.Response(200, json={"text": "Hello, World!"})

mounts = {"all://example.org": httpx.MockTransport(handler)}
client = httpx.Client(mounts=mounts)

添加对自定义方案的支持:

# Support URLs like "file:///Users/sylvia_green/websites/new_client/index.html"
mounts = {"file://": FileSystemTransport()}
client = httpx.Client(mounts=mounts)


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号