Skip to content

http_client: anchor response header lookup to line start - #12269

Open
univbyn-blip wants to merge 1 commit into
fluent:masterfrom
univbyn-blip:http_client-anchor-header-lookup
Open

http_client: anchor response header lookup to line start#12269
univbyn-blip wants to merge 1 commit into
fluent:masterfrom
univbyn-blip:http_client-anchor-header-lookup

Conversation

@univbyn-blip

@univbyn-blip univbyn-blip commented Aug 12, 2026

Copy link
Copy Markdown

PR Title

http_client: anchor response header lookup to line start

PR Body

Fixes #12267 (also explains #8525)

header_lookup() located response headers with an unanchored
strcasestr() over the response buffer. A header whose name embeds the
name of another header is matched by mistake: GCS S3-compatible
PutObject 200 responses include x-goog-stored-content-length: <N>
(the size of the stored object, always > 0) before the real
Content-Length: 0. The lookup for Content-Length: matched the tail
of x-goog-stored-content-length: , so content_length was parsed as
N and the client kept waiting for a response body that never arrives.
With the default net.io_timeout 0 the wait lasted until the server
reset the idle connection (~4 minutes on GCS), and every successful
upload was reported as a failure (http_do=-1 with HTTP Status: 200)
and retried — producing one duplicate object per attempt, indefinitely.

This change only accepts a match placed at the beginning of a line
(start of buffer or right after \n), so embedded header names are
skipped. Behavior for well-formed matches is unchanged.

Verified against a captured GCS PutObject response header block:
before: content_length = 26 (from x-goog-stored-content-length),
after: content_length = 0 (real header). AWS S3-style responses are
unaffected (no header embeds another header name).


Testing

Before we can approve your change; please submit the following in a comment:

  • Example configuration file for the change
  • Debug log output from testing the change
  • Attached Valgrind output that shows no leaks or memory corruption was found

(예: 여기에 이슈 #12267 의 재현 config / debug 로그를 코멘트로 첨부)

Documentation

  • N/A — bug fix, no user-facing configuration change

Backporting

  • Backport to latest stable release.

Summary by CodeRabbit

  • Bug Fixes
    • Improved HTTP header matching to recognize only complete header names at the start of a header line.
    • Prevented incorrect matches when a requested header name appears within another header’s name.
    • Continued searching when earlier occurrences are invalid, ensuring later valid matches are found.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8f9e3c0a-f1d9-4936-80c0-2ba68ff9376b

📥 Commits

Reviewing files that changed from the base of the PR and between ec28e4a and 1271795.

📒 Files selected for processing (1)
  • src/flb_http_client.c
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/flb_http_client.c

📝 Walkthrough

Walkthrough

The HTTP client now matches response headers only at the start of a header line. The lookup continues scanning after embedded matches until it finds a valid line-start match.

Changes

HTTP header parsing

Layer / File(s) Summary
Line-anchored header matching
src/flb_http_client.c
header_lookup performs a case-insensitive scan and accepts matches only at the response start or immediately after a newline. It skips rejected matches through the rest of their lines.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • fluent/fluent-bit#8791: Both PRs modify header_lookup() to prevent suffix matches and enforce HTTP header line boundaries.
  • fluent/fluent-bit#12268: Both PRs modify header_lookup() to anchor HTTP header-name matching at line starts.

Suggested reviewers: cosmo0920

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes anchoring response header lookup to the start of each line.
Linked Issues check ✅ Passed The change addresses issue #12267 by preventing embedded Content-Length matches and preserving valid response-header parsing.
Out of Scope Changes check ✅ Passed The changes are limited to the header lookup logic required to fix the linked GCS S3 upload failure.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/flb_http_client.c (1)

144-157: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add regression coverage for the line-start matching contract.

The visible test in tests/internal/http_client.c (Lines 652-689) checks only a valid X-Trace header. Add a response containing x-goog-stored-content-length: 26\r\nContent-Length: 0\r\n and assert that the parsed value is 0. Also test an embedded-only occurrence and assert FLB_HTTP_NOT_FOUND.

As per coding guidelines: “Validate both success and failure paths, including invalid payloads, boundary sizes, and null or missing fields.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/flb_http_client.c` around lines 144 - 157, Extend the HTTP client tests
around the existing X-Trace coverage to validate line-start header matching:
parse a response containing x-goog-stored-content-length followed by
Content-Length: 0 and assert the value is 0, then test a response where the
requested header appears only embedded in another header and assert
FLB_HTTP_NOT_FOUND.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/flb_http_client.c`:
- Around line 151-157: Update the header search loop around strcasestr so
rejected matches advance directly to the next newline rather than incrementing p
by one byte. Preserve matching only at the start of the response or immediately
after '\n', and stop safely at the end of c->resp.data to avoid rescanning the
response body.

---

Nitpick comments:
In `@src/flb_http_client.c`:
- Around line 144-157: Extend the HTTP client tests around the existing X-Trace
coverage to validate line-start header matching: parse a response containing
x-goog-stored-content-length followed by Content-Length: 0 and assert the value
is 0, then test a response where the requested header appears only embedded in
another header and assert FLB_HTTP_NOT_FOUND.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fba8c055-3be6-4c23-a296-d3dc163f5dfc

📥 Commits

Reviewing files that changed from the base of the PR and between ae51533 and ec28e4a.

📒 Files selected for processing (1)
  • src/flb_http_client.c

Comment thread src/flb_http_client.c
header_lookup() used an unanchored strcasestr() to find response
headers, so a header name that embeds the name of another header is
matched by mistake: GCS S3-compatible PutObject 200 responses include
'x-goog-stored-content-length: N' before 'Content-Length: 0', causing
content_length to be parsed as N and the client to wait for a body
that never arrives - every successful upload was judged as failed and
retried, creating duplicate objects.

Only accept a header match placed at the beginning of a line.

Fixes fluent#12267

Signed-off-by: yena <univbyn@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

1 participant