首页 / Node.js 教程 / URL 处理

Node.js 教程

URL 处理

本教程共 76 篇 · 第 23 篇 · 更新于 2026-07-25 · 约 4 分钟阅读

Node.jsURLWHATWG查询参数URLSearchParams

23. URL 处理

本节目标:WHATWG URL API 解析和构造 URL,处理查询参数。

Web 开发里天天跟 URL 打交道:解析请求参数、拼接接口地址、校验跳转链接。Node.js 内置了 WHATWG URL 标准实现,和现代浏览器用的是同一套 API,学完这里前端后端通用。

旧版的 url.parse() 虽然还在,但已经打上 Legacy 标签,新代码别再用了。

23.1 解析 URL

const url = new URL('https://user:pass@api.example.com:8080/v1/users?id=123#profile');

console.log(url.protocol);  // https:
console.log(url.username);  // user
console.log(url.password);  // pass
console.log(url.hostname);  // api.example.com
console.log(url.host);      // api.example.com:8080
console.log(url.port);      // 8080
console.log(url.pathname);  // /v1/users
console.log(url.search);    // ?id=123
console.log(url.hash);      // #profile
console.log(url.href);      // 完整 URL

new URL() 解析失败会直接抛 TypeError,不用像 url.parse 那样检查返回值。

23.2 相对路径解析

URL 构造函数的第二个参数是 base URL,用来解析相对路径:

const base = 'https://example.com/blog/';

new URL('2024/hello.html', base).href;
// https://example.com/blog/2024/hello.html

new URL('/about', base).href;
// https://example.com/about

new URL('../contact', base).href;
// https://example.com/contact

拼接 URL 时比字符串拼接安全得多,会自动处理斜杠、编码等问题。

23.3 URLSearchParams:查询参数

URL 实例上的 searchParams 返回一个 URLSearchParams 对象,专门操作 ? 后面的键值对:

const url = new URL('https://api.example.com/search?q=nodejs&page=1');
const params = url.searchParams;

params.get('q');        // nodejs
params.get('page');     // 1

params.set('page', '2');
params.append('sort', 'desc');
params.delete('filter');

console.log(url.search); // ?q=nodejs&page=2&sort=desc
console.log(url.href);   // 完整 URL 已更新
Note

URLSearchParams 修改后会自动同步回父 URL 对象,不需要手动赋值。

独立使用

不依附于 URL 对象,直接操作查询字符串:

const params = new URLSearchParams('name=Alice&age=30');

params.append('city', 'Beijing');
console.log(params.toString()); // name=Alice&age=30&city=Beijing

// 遍历
for (const [key, value] of params) {
  console.log(key, value);
}

// 转成普通对象(注意同名参数会丢失)
const obj = Object.fromEntries(params);

编码与解码

URLSearchParams 会自动对特殊字符做 encodeURIComponentdecodeURIComponent

const params = new URLSearchParams();
params.set('name', '张三');
params.set('redirect', 'https://a.com?x=1');

console.log(params.toString());
// name=%E5%BC%A0%E4%B8%89&redirect=https%3A%2F%2Fa.com%3Fx%3D1

如果你需要更精细的控制(比如只编码部分字符),可以手动调用 encodeURIComponent

23.4 路径拼接与文件 URL

Node.js 里经常要把文件路径转成 file:// 协议的 URL,比如动态 import() 时:

import { pathToFileURL } from 'node:url';
import { join } from 'node:path';

const filePath = join(process.cwd(), 'config.js');
const fileUrl = pathToFileURL(filePath);

console.log(fileUrl.href); // file:///C:/project/config.js (Windows)

// 用于动态 import
const mod = await import(fileUrl.href);

反过来,把 file:// URL 转回本地路径:

import { fileURLToPath } from 'node:url';

const __filename = fileURLToPath(import.meta.url);

23.5 url.parse 的迁移提示

老项目里你可能还见到这种代码:

import url from 'node:url';

const parsed = url.parse('https://example.com/path?a=1');
console.log(parsed.query); // 'a=1'

迁移到 URL 很简单:

旧写法新写法
url.parse(str).pathnamenew URL(str).pathname
url.parse(str).querynew URL(str).searchParams
url.parse(str).hostnew URL(str).host
url.parse(str, true).queryObject.fromEntries(new URL(str).searchParams)

唯一需要注意的是:url.parse 对格式错误的 URL 比较宽容,new URL() 更严格,非法格式会抛错。如果你的输入来源不可信,包一层 try/catch

function safeParseURL(input) {
  try {
    return new URL(input);
  } catch {
    return null;
  }
}

23.6 实战:构建安全的请求 URL

把本节内容串起来,写一个带签名参数的请求 URL 构建器:

import { createHash } from 'node:crypto';

function buildApiUrl(base, path, params, secret) {
  const url = new URL(path, base);

  // 填入业务参数
  Object.entries(params).forEach(([k, v]) => {
    url.searchParams.set(k, String(v));
  });

  // 加入时间戳
  url.searchParams.set('t', String(Date.now()));

  // 生成签名(实际项目用 HMAC,这里简化示例)
  const signBase = url.searchParams.toString() + secret;
  const sign = createHash('sha256').update(signBase).digest('hex');
  url.searchParams.set('sign', sign);

  return url.href;
}

const apiUrl = buildApiUrl(
  'https://api.example.com',
  '/v1/order',
  { userId: 10086, status: 'paid' },
  'my-secret-key'
);

console.log(apiUrl);