Skip to content

fix(relay): preserve queries in normalization and HTTP requests - #7450

Open
cuishuang wants to merge 1 commit into
block:mainfrom
cuishuang:main
Open

cuishuang wants to merge 1 commit into
block:mainfrom
cuishuang:main

Conversation

@cuishuang

@cuishuang cuishuang commented Sep 7, 2026 •

Copy link
Copy Markdown

Summary

Relay URL normalization could trim query values ending in / or rewrite nested URL schemes. Appending HTTP routes as strings also put routes inside query values: https://relay.example?token=abc/query requested / instead of /query?token=abc.

  • Parse relay URL components with url::Url and preserve query strings during normalization and scheme conversion.
  • Use a shared structural HTTP endpoint builder in CLI and ACP clients, preserving base paths and raw relay queries while appending endpoint query parameters. Cover bridge reads/writes, metadata, authenticated JSON requests (including one-shot commands), uploads and legacy fallback, and media downloads.
  • Preserve configured WebSocket paths and trailing slashes for NIP-42 authentication.
  • Exercise production clients against local HTTP servers and assert received paths, raw queries, and NIP-98 signed URLs.

Rebased onto upstream main at 96af488d968a1ae9d961c2132bea27822735f8da; the PR remains one signed-off commit.

Validation

  • cargo test -p buzz-core -p buzz-cli -p buzz-acp — 2087 passed, 4 ignored, no failures (unit, integration, and doc tests).
  • cargo clippy -p buzz-core -p buzz-cli -p buzz-acp --all-targets -- -D warnings — passed.
  • cargo fmt --all -- --check — passed.
  • CHECK_FILE_SIZES_BASE=96af488d968a1ae9d961c2132bea27822735f8da just file-size-check — passed.
  • Built the CLI and ran buzz channels list against a local HTTP fixture with root and /nostr/ relay bases. Verified the server received /query?... and /nostr/query?..., retained the raw query (escaping, duplicate keys, +, nested URL, trailing slash), and received matching signed URLs.

The repository-wide just ci attempt passed formatting but was stopped before workspace compilation after dependency downloads reduced free disk space below 4 GiB. The three affected packages were tested and linted separately as listed above. No live external relay was used.

@cuishuang
cuishuang requested a review from a team as a code owner September 7, 2026 12:42
@github-actions

github-actions Bot commented Sep 7, 2026 •

Copy link
Copy Markdown

🔐 Codex Security Review

Status: review required for the current range.

The current range is 96af488d968a1ae9d961c2132bea27822735f8da...2740197f87b2ab2b93259d3b1d12b49a6aa9d3c6.
A new review must complete for this exact range. When manual authorization
is required, a user with write access must comment exactly
@buzz-security-review 2740197f87b2ab2b93259d3b1d12b49a6aa9d3c6 to authorize a new review.
Any previous review applies only to its recorded range.

@salman1993 salman1993 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.

🤖 Major — query-bearing relay URLs still produce requests to the wrong endpoint (crates/buzz-cli/src/client.rs:1371)

The new normalizer now returns bases such as https://relay.example?token=abc, but every HTTP operation still appends its route with string formatting (for example, line 795 builds format!("{}/query", self.relay_url)). That yields https://relay.example?token=abc/query: /query is part of the query value and the request path remains /. A non-root input such as wss://relay.example/nostr/?token=abc similarly produces a request to /nostr/ with token=abc/query, not /nostr/query?token=abc. The ACP RestClient has the same composition pattern (relay.rs:292,460).

As a result, the exact query-bearing configurations this PR intends to support still cannot use the REST bridge: CLI commands and ACP context fetches hit the wrong route (typically 404 or the NIP-11 root) despite preserving the query text. Please compose endpoint paths structurally with Url while retaining the original query, and add a production-seam request test that asserts both the received path and query. The current normalization-only tests pass while missing this failure.

Validation at 8a5e8c1d21de0971a4598dd1542ea8a099f5c0ce: full cargo test -p buzz-core (256 unit + 2 doc), cargo test -p buzz-cli (464 unit; 1 ignored doc), and cargo test -p buzz-acp (916 unit + 9 integration) passed. FastValidator independently ran the three focused package/seam suites at the same SHA and confirmed query bytes survive normalization; that lane did not exercise request routing. No live relay run was performed.

@cuishuang

Copy link
Copy Markdown
Author

🤖 Major — query-bearing relay URLs still produce requests to the wrong endpoint (crates/buzz-cli/src/client.rs:1371)

The new normalizer now returns bases such as https://relay.example?token=abc, but every HTTP operation still appends its route with string formatting (for example, line 795 builds format!("{}/query", self.relay_url)). That yields https://relay.example?token=abc/query: /query is part of the query value and the request path remains /. A non-root input such as wss://relay.example/nostr/?token=abc similarly produces a request to /nostr/ with token=abc/query, not /nostr/query?token=abc. The ACP RestClient has the same composition pattern (relay.rs:292,460).

As a result, the exact query-bearing configurations this PR intends to support still cannot use the REST bridge: CLI commands and ACP context fetches hit the wrong route (typically 404 or the NIP-11 root) despite preserving the query text. Please compose endpoint paths structurally with Url while retaining the original query, and add a production-seam request test that asserts both the received path and query. The current normalization-only tests pass while missing this failure.

Validation at 8a5e8c1d21de0971a4598dd1542ea8a099f5c0ce: full cargo test -p buzz-core (256 unit + 2 doc), cargo test -p buzz-cli (464 unit; 1 ignored doc), and cargo test -p buzz-acp (916 unit + 9 integration) passed. FastValidator independently ran the three focused package/seam suites at the same SHA and confirmed query bytes survive normalization; that lane did not exercise request routing. No live relay run was performed.

@salman1993 Thanks. Modified. Please review it again.

Normalize relay URL components without modifying query values. Compose CLI and ACP HTTP endpoint paths with Url, preserving base paths and raw relay queries while appending endpoint query parameters.

Exercise production HTTP clients against local servers and assert received paths, raw queries, and NIP-98 signed URLs. Cover bridge reads and writes, metadata, uploads and their legacy fallback, and media downloads.

Signed-off-by: cuishuang <imcusg@gmail.com>
@cuishuang cuishuang changed the title fix(relay): preserve query strings during URL normalization fix(relay): preserve queries in normalization and HTTP requests Nov 7, 2026
@cuishuang

Copy link
Copy Markdown
Author

Thanks for catching this, @salman1993. I’ve updated the PR and rebased it onto main. The CLI and ACP REST clients now append endpoint paths using Url while preserving the original relay query. The new regression tests send requests to a local HTTP server and verify that it receives /query or /nostr/query, depending on the configured base path, with the original query intact.

Could you take another look at 2740197 when you have a chance? The PR workflows are also awaiting maintainer approval. Could someone with write access approve the runs and authorize the security review by posting @buzz-security-review 2740197 as a separate comment?

This branch has not been deployed

No deployments
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.

2 participants