mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-27 16:26:16 +08:00
4084b53834
Previously the proxy used reqwest for all upstream requests. reqwest normalizes header names to lowercase and reorders them internally, making proxied requests distinguishable from direct CLI requests. Some upstream providers are sensitive to these differences. This commit replaces reqwest with a hyper-based HTTP client on the default (non-proxy) path, achieving wire-level header fidelity: Server layer (server.rs): - Replace axum::serve with a manual hyper HTTP/1.1 accept loop - Enable preserve_header_case(true) so incoming header casing is captured in a HeaderCaseMap extension on each request - Bridge hyper requests to axum Router via tower::Service New hyper client module (hyper_client.rs): - Lazy-initialized hyper-util Client with preserve_header_case - ProxyResponse enum wrapping both hyper::Response and reqwest::Response behind a unified interface (status, headers, bytes, bytes_stream) - send_request() builds requests with ordered HeaderMap + case map Request handlers (handlers.rs): - Switch from (HeaderMap, Json<Value>) extractors to raw axum::extract::Request to preserve Extensions (containing the HeaderCaseMap from the accept loop) - Pass extensions through the forwarding chain Forwarder (forwarder.rs): - Remove HEADER_BLACKLIST array; replace with ordered header iteration that preserves original header sequence and casing - Build ordered_headers by iterating client headers, skipping only auth/host/content-length, and inserting auth headers at the original authorization position to maintain order - Handle anthropic-beta (ensure claude-code-20250219 tag) and anthropic-version (passthrough or default) inline during iteration - Remove should_force_identity_encoding() — accept-encoding is now transparently forwarded to upstream - Use hyper client by default; fall back to reqwest only when an HTTP/SOCKS5 proxy tunnel is configured Provider adapters (adapter.rs, claude.rs, codex.rs, gemini.rs): - Replace add_auth_headers(RequestBuilder) -> RequestBuilder with get_auth_headers(AuthInfo) -> Vec<(HeaderName, HeaderValue)> - Adapters now return header pairs instead of mutating a reqwest builder - Claude adapter: merge Anthropic/ClaudeAuth/Bearer into single branch; move Copilot fingerprint headers into get_auth_headers Response processing (response_processor.rs): - Add manual decompression (gzip/deflate/brotli via flate2 + brotli) for non-streaming responses, since reqwest auto-decompression is now disabled to allow accept-encoding passthrough - Add compressed-SSE warning log for streaming responses - Accept ProxyResponse instead of reqwest::Response HTTP client (http_client.rs): - Disable reqwest auto-decompression (.no_gzip/.no_brotli/.no_deflate) on both global and per-provider clients Streaming adapters (streaming.rs, streaming_responses.rs): - Generalize stream error type from reqwest::Error to generic E: Error Misc: - log_codes.rs: add SRV-005 (ACCEPT_ERR) and SRV-006 (CONN_ERR) - stream_check.rs: reformat copilot header lines - transform.rs: fix trailing whitespace alignment