Skip to content

fix: respect -pr http11 during retryablehttp fallback#2456

Closed
drmabus wants to merge 4 commits intoprojectdiscovery:devfrom
drmabus:fix-http11-fallback
Closed

fix: respect -pr http11 during retryablehttp fallback#2456
drmabus wants to merge 4 commits intoprojectdiscovery:devfrom
drmabus:fix-http11-fallback

Conversation

@drmabus
Copy link
Copy Markdown

@drmabus drmabus commented Mar 19, 2026

/claim #2240
Closes #2240

Summary

When -pr http11 is specified, httpx should strictly use HTTP/1.1.

However, retryablehttp may fall back to HTTPClient2 (which has HTTP/2 enabled)
on certain transport errors, bypassing the user's explicit protocol selection.

Fix

If HTTP/1.1 is forced, ensure HTTPClient2 reuses the same HTTP/1.1-only client,
preventing unintended HTTP/2 fallback.

Impact

  • Respects explicit protocol selection
  • Prevents silent HTTP/2 usage
  • Minimal and safe change

Testing

Verified locally:

Summary by CodeRabbit

  • Bug Fixes

    • Enforced HTTP/1.1 for configured client connections so primary and retry clients share the same transport, preventing unexpected protocol fallback during retries.
  • Tests

    • Added tests confirming that HTTP/1.1 configuration disables protocol fallback and that default settings preserve the existing retry behavior.

@auto-assign auto-assign bot requested a review from dogancanbakir March 19, 2026 05:14
@neo-by-projectdiscovery-dev
Copy link
Copy Markdown

neo-by-projectdiscovery-dev bot commented Mar 19, 2026

Neo - PR Security Review

No security issues found

Highlights

  • Minor modifications to HTTP/1.1 protocol enforcement tests
  • No functional changes to the underlying security fix
  • All security scanners returned clean results (0 findings)

Comment @pdneo help for available commands. · Open in Neo

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 19, 2026

Walkthrough

The New() constructor in common/httpx/httpx.go now uses the HTTP11 constant for protocol comparison and, when opts.Protocol == HTTP11, sets HTTPClient2 = HTTPClient so both primary and retryable clients share the HTTP/1.1-only transport (preventing HTTP/2 fallback).

Changes

Cohort / File(s) Summary
HTTP Client Protocol Enforcement
common/httpx/httpx.go
Replaced string-literal protocol check with the HTTP11 constant and updated New() to assign HTTPClient2 = HTTPClient when opts.Protocol == HTTP11, forcing the retryable client to use the same HTTP/1.1 transport.
Tests for Protocol Behavior
common/httpx/httpx_test.go
Added tests TestHTTP11ProtocolDisablesHTTP2Fallback and TestDefaultProtocolKeepsHTTP2Fallback to assert HTTPClient and HTTPClient2 are the same for HTTP11 and different for default options.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant NewConstructor as New()
    participant Primary as HTTPClient
    participant Retryable as HTTPClient2

    Caller->>NewConstructor: call New(opts) with opts.Protocol == HTTP11
    NewConstructor->>Primary: create HTTP/1.1-only transport
    NewConstructor->>Retryable: assign HTTPClient2 = HTTPClient
    NewConstructor-->>Caller: return client (both clients share transport)
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 I bind two clients with a hop and grin,
One woolly path, no HTTP/2 within,
Retries snug beside the primary stream,
No secret switches, one steady beam,
I munch the bytes and guard the seam. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: ensuring HTTP/1.1 protocol selection is respected during retryablehttp fallback behavior by forcing HTTPClient2 to reuse the HTTP/1.1 client.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@drmabus
Copy link
Copy Markdown
Author

drmabus commented Mar 19, 2026

Thanks for reviewing! Let me know if you'd like any changes or additional test cases.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@common/httpx/httpx.go`:
- Around line 186-191: Replace the string literal comparison against "http11"
with the Proto constant HTTP11: change the conditional that checks
httpx.Options.Protocol in the block that sets httpx.client.HTTPClient2 so it
compares against the HTTP11 constant (defined in proto.go) instead of the raw
string; also update the earlier occurrence around line 156 that currently
compares with "http11" to use HTTP11 for consistency, ensuring both checks use
the same Proto-typed constant.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7cb9d3cd-e3b0-4a42-ac05-f1b346be220c

📥 Commits

Reviewing files that changed from the base of the PR and between 0045108 and 67c9514.

📒 Files selected for processing (1)
  • common/httpx/httpx.go

@drmabus
Copy link
Copy Markdown
Author

drmabus commented Mar 19, 2026

Updated to use the HTTP11 constant instead of string literals for consistency. Thanks for the suggestion.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
common/httpx/httpx.go (1)

186-191: Consider adding a regression test for this fallback path.

This fix is small and targeted, but the bug only shows up when retryable fallback is triggered on specific transport failures. A test that forces that path and asserts HTTP/2 is never used when Protocol == HTTP11 would make this much harder to reintroduce.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@common/httpx/httpx.go` around lines 186 - 191, Add a regression test that
simulates a transport failure which triggers retryablehttp's fallback path and
verifies that when httpx.Options.Protocol == HTTP11 the code path in httpx.go
that sets httpx.client.HTTPClient2 = httpx.client.HTTPClient is effective (i.e.,
HTTP/2 is never used). Create a unit test (e.g.,
TestHTTP11NoHTTP2OnRetryFallback) that forces a retryable transport error, sets
Protocol to HTTP11, invokes the request flow that uses httpx.client, and asserts
the underlying client never negotiated or used HTTP/2 (inspect the transport or
request metadata/mock server to confirm). Ensure the test exercises the fallback
logic and fails if HTTPClient2 falls back to an HTTP/2-capable transport.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@common/httpx/httpx.go`:
- Around line 186-191: Add a regression test that simulates a transport failure
which triggers retryablehttp's fallback path and verifies that when
httpx.Options.Protocol == HTTP11 the code path in httpx.go that sets
httpx.client.HTTPClient2 = httpx.client.HTTPClient is effective (i.e., HTTP/2 is
never used). Create a unit test (e.g., TestHTTP11NoHTTP2OnRetryFallback) that
forces a retryable transport error, sets Protocol to HTTP11, invokes the request
flow that uses httpx.client, and asserts the underlying client never negotiated
or used HTTP/2 (inspect the transport or request metadata/mock server to
confirm). Ensure the test exercises the fallback logic and fails if HTTPClient2
falls back to an HTTP/2-capable transport.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 84628cf5-a39c-4f89-abae-b5d6de9a66ba

📥 Commits

Reviewing files that changed from the base of the PR and between 67c9514 and 4707072.

📒 Files selected for processing (1)
  • common/httpx/httpx.go

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@common/httpx/httpx_test.go`:
- Around line 16-24: The tests are asserting pointer identity but use
value-equality helpers; update TestDefaultProtocolKeepsHTTP2Fallback and the
other test to use require.Same/require.NotSame instead of
require.Equal/require.NotEqual when comparing ht.client.HTTPClient and
ht.client.HTTPClient2 so the assertions check that HTTPClient2 either references
the exact same instance (when Protocol is HTTP11) or a different instance (with
DefaultOptions/New); keep the rest of the test logic unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 57c5dfa8-6f7b-4ada-922d-9e19840dc83e

📥 Commits

Reviewing files that changed from the base of the PR and between 4707072 and 50997c1.

📒 Files selected for processing (1)
  • common/httpx/httpx_test.go

@Mzack9999
Copy link
Copy Markdown
Member

Thank you for the contribution! This issue has been resolved by merging #2424, which implements the same approach (HTTPClient2 = HTTPClient). Closing as the fix is now in dev. Appreciate the clean implementation and tests.

@Mzack9999 Mzack9999 closed this Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

-pr http11 flag is ignored on retryablehttp-go due to HTTP/2 fallback

2 participants