Skip to content

http: restore the "> " and "[fetch] " prefixes on verbose trace request lines - #38691

Open
robobun wants to merge 1 commit into
mainfrom
farm/5aec9e87/verbose-fetch-request-prefix
Open

http: restore the "> " and "[fetch] " prefixes on verbose trace request lines#38691
robobun wants to merge 1 commit into
mainfrom
farm/5aec9e87/verbose-fetch-request-prefix

Conversation

@robobun

@robobun robobun commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Problem

  • The verbose HTTP client trace (fetch(url, { verbose: true }), BUN_CONFIG_VERBOSE_FETCH=1|curl, bun install --verbose) is documented (docs/runtime/networking/fetch.mdx, docs/runtime/debugger.mdx) as printing request lines as [fetch] > HTTP/1.1 GET http://example.com/ / [fetch] > Connection: keep-alive and response lines as [fetch] < 200 OK.
  • Since the Rust port, request lines print without their prefix. Released 1.4.0, NO_COLOR=1:
     HTTP/1.1 GET http://localhost:35399/
     Authorization: Bearer [redacted]
     Connection: keep-alive
    < 200 OK
    < Content-Length: 2
    
    With colors (FORCE_COLOR=1 or a terminal) the response lines also carry the dim [fetch] tag and the request lines still carry nothing.
  • Cause, print_request in src/http/lib.rs:1439-1459: the three templates passed to pretty_errorln! start with a bare > . In the pretty template language a bare > is a tag terminator (<cyan>'s closing character) and is dropped (src/bun_core_macros/lib.rs:112, mirrored by pretty_fmt_runtime in src/bun_core/output.rs); a literal > has to be written \\>. The response side is unaffected because picohttp::Response's Display writes < through write_str, not through a template.
  • The [fetch] tag was dropped by the same port: the Zig printRequest wrote the tag plus > through the raw error writer, and the port replaced that with the templates above (the original port left a TODO(port) about the missing prefix, later removed without restoring it).

Fix

  • src/http/lib.rs print_request: the three templates escape the > ("{}\\> ..."), and each line starts with picohttp::trace_line_prefix().
  • src/picohttp/lib.rs: new trace_line_prefix() returns the <r><d>[fetch]<r> expansion when stderr has colors and "" otherwise, and Response's Display now uses it in place of its two inline copies of that condition and literal (same condition, same literal, so response output is byte for byte unchanged). The unused impl Display for picohttp::Request (a second, stale copy of the request format: hardcoded HTTP/1.1, no credential redaction, no callers since the port) is deleted rather than updated.
  • Why this is the right output: \\> is the established spelling of a literal > in these templates (src/install/lockfile/printer/tree_printer.rs -\\>, src/runtime/test_runner/expect/toHaveBeenCalled.rs \\>=, the \\<cmd\\> help texts), and taking the tag from the same function the response lines use makes the two halves of the trace line up the way the docs and the pre-port code had them; the tag staying color-only keeps plain (piped) output identical in shape to the response lines, which already behave that way.
  • Other templates in the tree with an unescaped > (the -> arrows in some bun install --verbose and bin-linker messages, etc.) are unrelated output and are not touched here.
  • Overlaps with http: escape control characters in the verbose request/response trace #38673 (control-character escaping in the same trace): the two changes are independent and both touch print_request's argument lists, Response's Display and the end of fetch.test.ts, so whichever lands second needs a trivial rebase.
  • Verified with test/js/web/fetch/fetch.test.ts:
    • new verbose fetch logging line prefixes block: verbose: true, BUN_CONFIG_VERBOSE_FETCH=1 and =curl (plain output: every trace line starts with > or < , exact first line > HTTP/1.1 GET <url>, the redacted Authorization line, a custom header, < 200 OK), and FORCE_COLOR=1 (every line starts with the exact \x1b[0m\x1b[2m[fetch]\x1b[0m bytes, and after Bun.stripANSI every line matches [fetch] > / [fetch] < ).
    • the existing [redacted] test now requires the > prefix instead of tolerating its absence (>?), which is how this went unnoticed.
    • All five fail on the released binary (request lines start with a space) and pass with this branch; test/regression/issue/12042.test.ts (curl trace) still passes. The rest of fetch.test.ts has the same set of localhost/IPv6 and root-permission failures here with and without this change.
    • cargo check -p bun_picohttp -p bun_http and cargo fmt are clean.

Background

  • Pretty templates: pretty_errorln! and friends take a template in which <cyan>, <d> (dim), <r> (reset) and so on are rewritten at compile time into ANSI escapes, or stripped when the destination has no colors (bun_core::pretty_fmt!). Only the template is rewritten; {} arguments are substituted afterwards and are never scanned for tags, which is why header values containing > were always printed intact and only the template's own > went missing.
  • HTTPVerboseLevel::Headers prints the > / < lines; Curl additionally prints a copy-pasteable curl command first. HTTP/1.1, h2 and h3 all call the same print_request, so the three protocols share this fix; print_response formats the response through picohttp::Response's Display.
  • FORCE_COLOR=1 makes Output enable colors on a piped stderr (and overrides NO_COLOR), which is how the color case is exercised from a test.

…st lines

print_request passed "> ..." templates to pretty_errorln!, which drops a
bare ">" as a tag terminator, so request lines printed as " HTTP/1.1 GET
url" while response lines printed "< 200 OK". Escape the ">" and print
the same "[fetch] " tag the response lines carry on color terminals,
via a shared picohttp::trace_line_prefix(). Delete the unused
Display impl for picohttp::Request.
@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@robobun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 17 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: a5a19dfd-ee43-45ca-8009-68f5377d58b7

📥 Commits

Reviewing files that changed from the base of the PR and between 9805144 and 4b073d2.

📒 Files selected for processing (3)
  • src/http/lib.rs
  • src/picohttp/lib.rs
  • test/js/web/fetch/fetch.test.ts

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

@robobun

robobun commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator Author

Status: reproduced on the released 1.4.0 (NO_COLOR=1 and FORCE_COLOR=1 against a local Bun.serve; request lines print as HTTP/1.1 GET ... with no > and no [fetch] tag while response lines print < 200 OK / [fetch] < 200 OK). Fix and tests are in this PR; the five assertions in test/js/web/fetch/fetch.test.ts fail on the released binary and pass with this branch. Waiting on CI.

@claude claude Bot left a comment

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.

LGTM — a targeted fix restoring the documented > and [fetch] prefixes on verbose fetch request lines.

What was reviewed:

  • Confirmed the root cause in bun_core_macros/lib.rs: a bare > is dropped as a tag terminator, and \\> is the established literal escape (matching tree_printer.rs, toHaveBeenCalled.rs, etc.).
  • Verified trace_line_prefix() produces byte-identical output to the inline condition it replaces in Response::fmt, so response lines are unchanged.
  • Grepped for any caller of the deleted impl Display for picohttp::Request — none exist; print_request is the only request formatter and it never used it.
  • Tests cover verbose: true, BUN_CONFIG_VERBOSE_FETCH=1|curl, and FORCE_COLOR=1; the tightened [redacted] regex now requires the > prefix instead of tolerating its absence.
Extended reasoning...

Overview

This PR restores two prefixes that went missing from the verbose HTTP client trace during the Rust port: the > marker on request lines and the dim [fetch] tag (color-only). The changes are:

  • src/http/lib.rs (print_request): The three pretty_errorln! templates now escape > as \\> and interpolate picohttp::trace_line_prefix() as the first argument. I confirmed in src/bun_core_macros/lib.rs:96-114 that a bare > in a pretty template is silently dropped as a stray tag closer, while \\> emits a literal > — this is the same escape used throughout the tree (tree_printer.rs, clap/lib.rs, help texts).
  • src/picohttp/lib.rs: A new trace_line_prefix() helper returns the ANSI-expanded [fetch] tag when stderr has colors and "" otherwise. Response::fmt now calls it in place of two inline copies of the identical condition/literal — the response output is byte-for-byte unchanged. The unused impl Display for Request<'_> (stale: hardcoded HTTP/1.1, no credential redaction) is deleted; I grepped for picohttp::Request display uses and confirmed there are none.
  • test/js/web/fetch/fetch.test.ts: A new describe.concurrent block with four tests covering verbose: true, BUN_CONFIG_VERBOSE_FETCH=1, =curl, and FORCE_COLOR=1, plus the existing [redacted] test tightened from >? to require the prefix.

Security risks

None. This is purely debug-trace output formatting to stderr. Credential redaction (Authorization: Bearer [redacted]) is preserved and now covered by two additional test assertions. The prefix is passed as a {} argument, and the macro only rewrites the template literal — arguments are substituted after tag expansion — so no template-injection concern arises from the interpolated prefix.

Level of scrutiny

Low-to-medium. This is a cosmetic regression fix in diagnostic output with no runtime-behavior implications beyond what's printed to stderr. The mechanism (pretty-template escaping) is well-understood and the fix follows the exact pattern used elsewhere in the codebase. The deleted Display impl was verifiably dead. The refactor of Response::fmt to use the shared helper is a straightforward deduplication with identical semantics.

Other factors

  • The PR description is thorough: it names the exact source line where > is dropped, cites prior art for \\>, and explains why the [fetch] tag is color-only (matching pre-port and response-side behavior).
  • Test coverage is strong: exact first-line assertions, every-line-prefixed assertions via filter, both plain and ANSI paths, and the negative check that the raw token doesn't leak. Tests use bunEnv spread, port: 0, describe.concurrent, and drain both pipes concurrently — all matching harness conventions.
  • The PR notes overlap with #38673 and that whichever lands second needs a trivial rebase; this PR's HEAD (4b073d2) is already on main, so that has been resolved.
  • No prior human or bot reviews to address; CodeRabbit was rate-limited.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant