Skip to content

fix(node): parse absolute-form request targets - #85

Merged
dinwwwh merged 1 commit into
mainfrom
fix/node-absolute-form-request-target
Sep 5, 2026
Merged

fix(node): parse absolute-form request targets#85
dinwwwh merged 1 commit into
mainfrom
fix/node-absolute-form-request-target

Conversation

@dinwwwh

@dinwwwh dinwwwh commented Sep 5, 2026

Copy link
Copy Markdown
Member

HTTP/1.1 clients that treat the server as a forward proxy (curl -x <server> <url>, HTTP_PROXY pointed at the app, some intermediaries) send the request target in absolute-form, GET http://host:port/ping HTTP/1.1, and Node hands that string through as req.url verbatim. toStandardUrl prefixed it with /, so routers saw /http://host:port/ping and answered 404. Absolute-form targets are now parsed with URL and reduced to pathname + search + hash through the Fetch adapter's toStandardUrl, so the Node and Fetch adapters yield the same StandardUrl for the same request.

Supersedes #81. Thanks @javascript-unsafe for the report and the initial fix.

Fixes

  • GET http://127.0.0.1:3000/ping?x=1 against a real node:http server now yields /ping?x=1. The Fastify adapter inherits this through req.raw.
  • Origin-form paths are still passed through untouched: no normalization, and //evil.com/x stays a path rather than a host.
  • Unparseable absolute-form input (http://, http://[::1, an out-of-range port) keeps the previous /${url} fallback instead of throwing.

Testing

  • Unit tests cover origin-form, originalUrl precedence, absolute-form, normalization parity with the Fetch adapter, non-http schemes, and malicious or malformed input ported from oRPC's standard-server-node tests.
  • One test sends absolute-form over a raw socket to a live node:http server.
  • Full suite, eslint, and tsc -b pass.

@pkg-pr-new

pkg-pr-new Bot commented Sep 5, 2026

Copy link
Copy Markdown
@standardserver/aws-lambda

npm i https://pkg.pr.new/@standardserver/aws-lambda@85

@standardserver/core

npm i https://pkg.pr.new/@standardserver/core@85

@standardserver/fastify

npm i https://pkg.pr.new/@standardserver/fastify@85

@standardserver/fetch

npm i https://pkg.pr.new/@standardserver/fetch@85

@standardserver/node

npm i https://pkg.pr.new/@standardserver/node@85

@standardserver/peer

npm i https://pkg.pr.new/@standardserver/peer@85

@standardserver/shared

npm i https://pkg.pr.new/@standardserver/shared@85

commit: e67d542

Co-authored-by: Xia Chao <236466140+bun-unsafe@users.noreply.github.com>
@dinwwwh
dinwwwh force-pushed the fix/node-absolute-form-request-target branch from ea692c5 to e67d542 Compare September 5, 2026 03:56
@codspeed-hq

codspeed-hq Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 26 untouched benchmarks
⏩ 108 skipped benchmarks1


Comparing fix/node-absolute-form-request-target (e67d542) with main (f13e415)

Open in CodSpeed

Footnotes

  1. 108 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

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

ℹ️ Minor suggestions only — the absolute-form parsing fix is correct and the new test coverage genuinely discriminates against the old behavior.

Reviewed changes — initial review of PR #85 (commit e67d542 vs base f13e415).

  • packages/node/src/url.tstoStandardUrl now short-circuits origin-form targets unchanged and reduces absolute-form (and other URL-parseable) targets to pathname + search + hash via new URL(url, 'http://localhost') + the Fetch adapter's toStandardUrl, falling back to /${url} on parse errors.
  • packages/node/src/url.test.ts — expanded from one case to seven it blocks covering origin-form (incl. *), originalUrl precedence with absolute-form, absolute-form collapsing, non-http schemes, relative-path fallbacks, malicious/malformed input, and a raw-socket round-trip against a live node:http server that would have failed on the old /${url} prefixing.

ℹ️ Nitpicks

  • url.ts:9-14 — the startsWith('/') early-return ordering is load-bearing: it is the only thing keeping an origin-form target like //evil.com/ping from being host-resolved to /ping by new URL. A one-line comment recording that this ordering is intentional (plus why the 'http://localhost' base exists only to coerce fallback strings) would stop a future cleanup from silently reintroducing the hostization the malicious-input tests guard against.

Pullfrog  | Fix it ➔View workflow run | Using DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏

@dinwwwh
dinwwwh merged commit 63c66ad into main Sep 5, 2026
7 of 8 checks passed
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