fix(node): parse HTTP absolute-form request URLs - #81
Conversation
There was a problem hiding this comment.
ℹ️ No critical issues — one minor suggestion inline.
Reviewed changes
fromAbsoluteHttpUrl(url)— new helper inpackages/node/src/url.tsthat parseshttp:/https:absolute-form request targets withnew URLand returnspathname + search + hash, matching the Fetch adapter (packages/fetch/src/url.ts), returningundefinedfor unparseable input or non-http schemes.toStandardUrl(req)— origin-form (/…) URLs now pass through untouched; absolute-form URLs go through the helper; everything else keeps the previous/${url}fallback.- Tests — five new exact-match cases in
packages/node/src/url.test.tscovering absolute-form canonicalization (path, query, hash), scheme case-insensitivity, and absolute-form viaoriginalUrl.
The change is correctly shaped: Node hands req.url the raw request-target, so only absolute-form is affected, and I mutation-checked that reverting the fix fails the new tests. I also verified the fallback paths empirically (non-http schemes like ftp: and CONNECT authority-form host:443 still map to /${url}). The only gap is a test for the scheme-guard branch, covered inline.
DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏
| expect(toStandardUrl({ url: '/foo?bar=1#baz' } as any)).toBe('/foo?bar=1#baz') | ||
| expect(toStandardUrl({ url: '/', originalUrl: '/foo?bar=2#baz' } as any)).toBe('/foo?bar=2#baz') | ||
| expect(toStandardUrl({ url: 'base' } as any)).toBe('/base') | ||
| expect(toStandardUrl({ url: 'http://127.0.0.1:3000/ping' } as any)).toBe('/ping') |
There was a problem hiding this comment.
Worth pinning the scheme-guard fallback branch: every new case here is an http(s) URL, so parsed.protocol !== 'http:' && parsed.protocol !== 'https:' in fromAbsoluteHttpUrl is the only branch still uncovered — new URL('ftp://example.com/x') parses fine, and dropping that guard would silently change it from /ftp://example.com/x to /x with no test noticing. Adding expect(toStandardUrl({ url: 'ftp://example.com/x' } as any)).toBe('/ftp://example.com/x') would lock in the documented "non-http schemes still get the previous /${url} behavior".

Problem
toStandardUrltreated anyreq.urlthat does not start with/as a relative path and prefixed/.HTTP/1.1 absolute-form request targets (common from proxies) look like
http://127.0.0.1:3000/ping. That became/http://127.0.0.1:3000/ping, so consumers such as oRPC's NodeRPCHandlerfailed to match the procedure and returned 404.Origin-form (
/ping) was already correct. The Fetch adapter already usesURL.pathname + search + hash.Fix
If the request target is an
http:orhttps:URL, parse it withURLand return pathname + search + hash, matching the Fetch adapter.Unparseable values and non-http schemes still get the previous
/${url}behavior (for examplebase→/base).Testing