Skip to content

fix: force HTTP/1.1 for LLM API requests#22

Open
efecnc wants to merge 3 commits intoaltaidevorg:mainfrom
efecnc:fix/force-http1-for-llm-requests
Open

fix: force HTTP/1.1 for LLM API requests#22
efecnc wants to merge 3 commits intoaltaidevorg:mainfrom
efecnc:fix/force-http1-for-llm-requests

Conversation

@efecnc
Copy link
Copy Markdown
Contributor

@efecnc efecnc commented May 6, 2026

Summary

  • Forces HTTP/1.1 for all LLM API requests by adding .http1_only() to the shared reqwest client builder
  • Fixes "error decoding response body" failures with reasoning models (deepseek-v4-pro, deepseek-reasoner)

Problem

reqwest with rustls-tls negotiates HTTP/2 via ALPN. DeepSeek's API (behind CloudFront) has HTTP/2 body-framing issues on long-running responses — when a reasoning model takes >30s to respond, the HTTP/2 stream frame boundaries can corrupt or truncate the response body, causing reqwest's .text().await to fail with "error decoding response body."

This error persisted even after PR #20 increased the timeout to 600s, confirming it's not a timeout issue but an HTTP/2 protocol-level problem.

Why HTTP/1.1

  • Single-request LLM API calls have zero performance benefit from HTTP/2 multiplexing
  • HTTP/1.1 has decades of battle-tested reliability for simple request-response patterns
  • Eliminates an entire class of hard-to-debug protocol errors
  • No impact on other features (web_search, web_fetch use separate clients)

Test plan

  • Verify deepseek-v4-pro completes requests without "error decoding response body"
  • Verify Gemini, OpenAI, OpenRouter providers still work normally
  • Confirm no regression for Anthropic provider (uses separate client path)

reqwest with rustls-tls negotiates HTTP/2 via ALPN, but some API
servers (notably DeepSeek behind CloudFront) have body-framing issues
with HTTP/2 on long-running responses. This causes reqwest to fail
with "error decoding response body" when the response takes >30s
(common for reasoning models like deepseek-v4-pro).

Forcing HTTP/1.1 avoids this class of errors entirely without any
performance penalty for single-request LLM calls.
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modifies the global reqwest client builder in src/utils.rs to force HTTP/1.1. The review feedback identifies that this change impacts the Anthropic provider, contrary to the PR's initial assumptions, and suggests adding a code comment to document the rationale for this protocol restriction to avoid future regressions.

Comment thread src/utils.rs
pub fn build_reqwest_client() -> reqwest::Client {
reqwest::Client::builder()
.no_proxy()
.http1_only()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The PR description's assumption that the Anthropic provider uses a separate client path and is unaffected is incorrect; AnthropicProvider in src/provider.rs (line 92) calls this build_reqwest_client() function. Consequently, this change forces HTTP/1.1 for Anthropic as well, which contradicts the stated test plan and indicates that this provider may not have been verified with the protocol change.

Comment thread src/utils.rs
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@efecnc
Copy link
Copy Markdown
Contributor Author

efecnc commented May 6, 2026

REJECTED — Over-engineering

This PR forces HTTP/1.1 for all providers to fix a problem that only affects DeepSeek behind CloudFront.

Problems:

  1. Overly broad: Disables HTTP/2 for OpenAI, Gemini, Anthropic, OpenRouter when only DeepSeek needs the fix
  2. Anthropic is affected (contrary to PR description): AnthropicProvider::new() in src/provider.rs:92 calls build_reqwest_client()
  3. Better fix: Apply .http1_only() only to the DeepSeek client path, or make it configurable per-provider

Recommendation:

Close this PR. The correct approach is provider-specific — add .http1_only() only where it's actually needed.

@efecnc efecnc closed this May 6, 2026
The original fix forced HTTP/1.1 for ALL providers via .http1_only() on
the shared build_reqwest_client(), affecting OpenAI, Gemini, Anthropic,
and OpenRouter when only DeepSeek behind CloudFront has the HTTP/2
body-framing issue.

Changes:
- Revert .http1_only() from build_reqwest_client() (no longer global)
- Add build_reqwest_client_http1() for providers that need HTTP/1.1
- LLMClient::new_openai_compatible() stays HTTP/2-capable (default)
- LLMClient::new_openai_compatible_http1() forces HTTP/1.1
- create_provider() checks provider_name for 'deepseek' and routes to
  the HTTP/1.1 client only for DeepSeek providers
@efecnc efecnc reopened this May 6, 2026
@efecnc
Copy link
Copy Markdown
Contributor Author

efecnc commented May 6, 2026

Reopened with provider-specific fix

The original concern (close comment below) was that .http1_only() was applied globally via build_reqwest_client(), affecting all providers. Fixed in commit 1849e8e:

Changes

  • Removed .http1_only() from build_reqwest_client() — OpenAI, Gemini, Anthropic, OpenRouter now use HTTP/2 normally
  • Added build_reqwest_client_http1() — separate builder that forces HTTP/1.1
  • LLMClient::new_openai_compatible() — stays HTTP/2-capable (default for all OpenAI-compatible providers)
  • LLMClient::new_openai_compatible_http1() — forces HTTP/1.1
  • create_provider() — checks provider_name for "deepseek" (case-insensitive) and routes only DeepSeek providers to the HTTP/1.1 client

What changed from the original PR

Before (over-engineered) After (targeted)
.http1_only() on shared build_reqwest_client() .http1_only() only for DeepSeek
All providers forced to HTTP/1.1 Only DeepSeek gets HTTP/1.1
Anthropic affected (contrary to PR claims) Anthropic unaffected (uses default build_reqwest_client())

Files changed

  • src/utils.rs: split build_reqwest_client()build_reqwest_client() + build_reqwest_client_http1(); added new_openai_compatible_http1()
  • src/provider.rs: create_provider() routes DeepSeek → HTTP/1.1 client

Verification

  • cargo check passes
  • cargo test --lib utils::tests passes (4/4)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant