Node.js:直接用WHATWG URL解析req.url报错,需从旧URL API迁移
解决Node.js中WHATWG URL构造函数解析req.url报错的问题
环境信息:Node.js v18.15.0、Ubuntu 22.04、NPM 9.5.0
在创建Node.js HTTP服务器路由时,直接将req.url传入WHATWG URL构造函数会抛出无效URL错误,报错代码如下:
const httpServer = http.createServer((req, res) => { res.writeHead(200, {'Content-Type': 'text/html'}); const requestURL = new URL(req.url); const requestHostname = requestURL.hostname; const requestPathname = requestURL.pathname; const requestParams = requestURL.searchParams; console.log(requestPathname); });
对应的报错信息:
node:internal/url:566 throw new ERR_INVALID_URL(input); ^ TypeError [ERR_INVALID_URL]: Invalid URL at new NodeError (node:internal/errors:399:5) at URL.onParseError (node:internal/url:566:9) at new URL (node:internal/url:646:5) at Server.<anonymous> (/var/www/newsat11.live/index.js:26:24) at Server.emit (node:events:513:28) at parserOnIncoming (node:_http_server:1072:12) at HTTPParser.parserOnHeadersComplete (node:_http_common:119:17) { input: '/', code: 'ERR_INVALID_URL' } Node.js v18.15.0
而使用Node.js URL模块的传统API url.parse(req.url) 则可正常运行:
const httpServer = http.createServer((req, res) => { res.writeHead(200, {'Content-Type': 'text/html'}); const requestURL = url.parse(req.url); const requestHostname = requestURL.hostname; const requestPathname = requestURL.pathname; const requestParams = requestURL.searchParams; console.log(requestPathname); // logs "/" as the pathname for localhost });
问题原因
WHATWG URL构造函数要求传入完整的URL字符串(必须包含协议、主机等核心部分),但req.url仅包含请求的路径和查询参数(比如/或/api?foo=bar),并非完整URL,因此会触发无效URL错误。而传统的url.parse方法支持解析相对路径,所以可以正常工作。
解决方案
通过拼接协议和请求头中的host字段,构造完整的URL后再传入WHATWG URL构造函数。示例代码如下:
const httpServer = http.createServer((req, res) => { res.writeHead(200, {'Content-Type': 'text/html'}); // 拼接完整URL:协议(这里用http,若为HTTPS则替换为https)+ host + req.url const fullURL = `http://${req.headers.host}${req.url}`; const requestURL = new URL(fullURL); const requestHostname = requestURL.hostname; const requestPathname = requestURL.pathname; const requestParams = requestURL.searchParams; console.log(requestPathname); });
如果服务器运行在HTTPS环境下,只需将协议部分改为https://即可:
const fullURL = `https://${req.headers.host}${req.url}`;
内容的提问来源于stack exchange,提问作者Newsat11
相关产品推荐
相关产品推荐

