🔸 第一部分:httpx
请求入口
我们从最常用的入口开始,看看如何使用httpx
库发送HTTP请求。通常,我们会使用 httpx.get()
或 httpx.post()
方法:
import httpx response = httpx.get('https://example.com') print(response.status_code) print(response.text)
🔹 这些方法的背后到底发生了什么呢?我们从httpx.get()
方法的实现看起。
🔸 第二部分:get方法的实现
httpx.get()
只是对 httpx.request()
方法的简单封装:
# httpx/_api.py def get(url: str, *, params: dict = None, headers: dict = None, cookies: dict = None, auth = None, timeout = None, allow_redirects: bool = True, **kwargs): return request("GET", url, params=params, headers=headers, cookies=cookies, auth=auth, timeout=timeout, allow_redirects=allow_redirects, **kwargs)
🔹 get()
方法将请求方法设置为"GET",然后调用内部的 request()
方法。让我们深入 request()
方法。
🔸 第三部分:request方法揭秘
request()
方法是 httpx
库的核心方法,负责处理所有类型的HTTP请求:
# httpx/_api.py def request( method: str, url: str, *, params: dict = None, data: dict = None, json: dict = None, headers: dict = None, cookies: dict = None, files: dict = None, auth = None, timeout = None, allow_redirects: bool = True, **kwargs ): with Client() as client: return client.request( method, url, params=params, data=data, json=json, headers=headers, cookies=cookies, files=files, auth=auth, timeout=timeout, allow_redirects=allow_redirects, **kwargs )
🔹 request()
方法创建一个 Client
对象,并调用 client.request()
来实际发送请求。接下来,我们看看 Client
对象的实现。
🔸 第四部分:Client对象的奥秘
Client
对象在httpx
库中扮演了重要角色。它不仅可以发送请求,还能管理会话和连接:
# httpx/_client.py class Client(BaseClient): def request( self, method: str, url: str, *, params: dict = None, data: dict = None, json: dict = None, headers: dict = None, cookies: dict = None, files: dict = None, auth = None, timeout = None, allow_redirects: bool = True, **kwargs ): request = self.build_request( method, url, params=params, data=data, json=json, headers=headers, cookies=cookies, files=files, auth=auth ) response = self.send(request, timeout=timeout, allow_redirects=allow_redirects, **kwargs) return response
🔹 Client
对象的 request()
方法中首先调用 build_request()
方法来构建 Request
对象。然后调用 send()
方法来发送请求。
🔸 第五部分:Request对象的构建
build_request()
方法负责构建一个 Request
对象:
# httpx/_client.py class Client(BaseClient): def build_request( self, method: str, url: str, *, params: dict = None, data: dict = None, json: dict = None, headers: dict = None, cookies: dict = None, files: dict = None, auth = None ) -> Request: request = Request( method=method, url=url, params=params, data=data, json=json, headers=headers, cookies=cookies, files=files, auth=auth, ) return request
🔹 build_request()
方法中,将请求的方法、URL、头信息、数据等封装到 Request
对象中。
🔸 第六部分:发送请求
当请求准备好后,Client
对象的 send()
方法负责实际发送HTTP请求:
# httpx/_client.py class Client(BaseClient): def send( self, request: Request, *, stream: bool = False, timeout = None, allow_redirects: bool = True, **kwargs ) -> Response: response = self._send_handling_redirects(request, timeout=timeout, allow_redirects=allow_redirects, **kwargs) return response
🔹 send()
方法会处理重定向和超时等情况,通过调用 _send_handling_redirects()
方法来实际发送请求。
🔸 第七部分:处理重定向
_send_handling_redirects()
方法负责处理请求的重定向逻辑:
# httpx/_client.py class Client(BaseClient): def _send_handling_redirects( self, request: Request, *, timeout = None, allow_redirects: bool = True, **kwargs ) -> Response: response = self._send_single_request(request, timeout=timeout, **kwargs) while response.is_redirect and allow_redirects: request = self.build_request("GET", response.headers["location"]) response = self._send_single_request(request, timeout=timeout, **kwargs) return response
🔹 通过检查响应的重定向状态并构建新的请求对象,_send_handling_redirects()
方法确保了所有重定向都能被正确处理。
🔸 第八部分:发送单个请求
_send_single_request()
方法通过底层的transport
来实际发送请求:
# httpx/_client.py class Client(BaseClient): def _send_single_request(self, request: Request, timeout = None, **kwargs) -> Response: transport = self._transport_for_url(request.url) response = transport.handle_request(request, timeout=timeout) return response
🔹 _send_single_request()
方法中最重要的一步是调用 transport.handle_request()
方法来实际发送请求。
🔸 总结
🔹 通过以上解析,我们了解了 httpx
库从发送请求到接收响应的全过程。从 httpx.get()
方法开始,经过 Client
对象的处理、Request
的构建、请求的发送和重定向的处理,最终构建 Response
对象。这一系列流程确保了 httpx
库能够简洁、高效地处理HTTP请求,让开发者可以专注于业务逻辑的实现。