Build a Chrome-compliant ordered header dict. Header order follows Chrome's HTTP/2 frame ordering as captured via packet inspection (Charles Proxy / Wireshark): 1. sec-ch-ua group (Chrome/Edge only – low-entropy Client Hints) 2. content-type (body requests only)
(
self,
*,
method: str,
headers: dict[str, str] | None,
user_agent: str | None,
browser_impersonate: str | None,
has_body: bool = False,
sec_fetch_site: str = "same-origin",
)
| 176 | "上游请求失败", |
| 177 | details={"transport": self.transport_name, "url": url, "reason": str(exc)}, |
| 178 | ) from exc |
| 179 | finally: |
| 180 | session.close() |
| 181 | |
| 182 | try: |
| 183 | kwargs = { |
| 184 | "method": method.upper(), |
| 185 | "url": url, |
| 186 | "headers": headers, |
| 187 | "cookies": cookies, |
| 188 | "params": params, |
| 189 | } |
| 190 | if json_body is not None: |
| 191 | kwargs["json"] = json_body |
| 192 | if form_body is not None: |
| 193 | kwargs["data"] = form_body |
| 194 | client_kwargs: dict[str, Any] = { |
| 195 | "timeout": self.settings.request_timeout_seconds, |
| 196 | "follow_redirects": True, |
| 197 | "trust_env": False, |
| 198 | } |
| 199 | if proxy_url: |
| 200 | client_kwargs["proxy"] = proxy_url |
| 201 | with httpx.Client(**client_kwargs) as client: |
| 202 | return client.request(**kwargs) |
| 203 | except Exception as exc: |
| 204 | raise UpstreamRequestError( |
| 205 | "上游请求失败", |
| 206 | details={"transport": self.transport_name, "url": url, "reason": str(exc)}, |
| 207 | ) from exc |
| 208 | |
| 209 | def _decode_response(self, *, response: Any, url: str): |
| 210 | self._ensure_success(response=response, url=url) |
| 211 | try: |
| 212 | payload = response.json() |
| 213 | except Exception as exc: |
| 214 | raise UpstreamRequestError( |
| 215 | "上游返回了非 JSON 数据", |
| 216 | details={ |
| 217 | "transport": self.transport_name, |
| 218 | "url": url, |
| 219 | "status_code": getattr(response, "status_code", "unknown"), |
| 220 | "body_preview": getattr(response, "text", "")[:500], |
| 221 | }, |
| 222 | ) from exc |
| 223 | |
| 224 | return payload |
| 225 | |
| 226 | def _ensure_success(self, *, response: Any, url: str) -> None: |
| 227 | status_code = int(getattr(response, "status_code", 0) or 0) |
| 228 | if status_code < 400: |
| 229 | return |
| 230 | body_preview = str(getattr(response, "text", ""))[:500] |
| 231 | raise UpstreamRequestError( |
| 232 | "上游接口返回错误", |
| 233 | details={"url": url, "status_code": status_code, "body_preview": body_preview}, |
| 234 | ) |
| 235 |
no test coverage detected