Node.js中URL模块详解

Node.js 中 URL 模块全部 API 详解

1. URL 类

javascript 复制代码
const { URL } = require('url');

// 1. 创建 URL 对象
const url = new URL('https://www.example.com:8080/path?query=value#hash');

// 2. URL 属性
console.log('协议:', url.protocol);      // 'https:'
console.log('主机名:', url.hostname);    // 'www.example.com'
console.log('端口:', url.port);          // '8080'
console.log('主机:', url.host);          // 'www.example.com:8080'
console.log('路径:', url.pathname);      // '/path'
console.log('查询字符串:', url.search);   // '?query=value'
console.log('查询参数:', url.searchParams); // URLSearchParams 对象
console.log('哈希:', url.hash);          // '#hash'
console.log('完整 URL:', url.href);      // 'https://www.example.com:8080/path?query=value#hash'
console.log('源:', url.origin);          // 'https://www.example.com'
console.log('用户名:', url.username);    // ''
console.log('密码:', url.password);      // ''

// 3. 修改 URL 属性
url.protocol = 'http:';
url.hostname = 'example.com';
url.port = '80';
url.pathname = '/new-path';
url.search = '?new=query';
url.hash = '#new-hash';
url.username = 'user';
url.password = 'pass';

// 4. URL 字符串化
console.log('URL 字符串:', url.toString());
console.log('URL JSON:', url.toJSON());

2. URLSearchParams 类

javascript 复制代码
const { URLSearchParams } = require('url');

// 1. 创建 URLSearchParams 对象
const params = new URLSearchParams('key1=value1&key2=value2');

// 2. 添加参数
params.append('key3', 'value3');
params.append('key3', 'value4'); // 可以添加同名参数

// 3. 获取参数
console.log('获取参数:', params.get('key1'));     // 'value1'
console.log('获取所有参数:', params.getAll('key3')); // ['value3', 'value4']

// 4. 检查参数是否存在
console.log('参数是否存在:', params.has('key1')); // true

// 5. 删除参数
params.delete('key2');

// 6. 设置参数
params.set('key1', 'new-value'); // 替换已存在的参数

// 7. 遍历参数
for (const [key, value] of params) {
  console.log(`${key}: ${value}`);
}

// 8. 转换为字符串
console.log('参数字符串:', params.toString());

// 9. 排序参数
params.sort();

// 10. 清空参数
params.forEach((value, key) => {
  params.delete(key);
});

3. URL 解析和格式化

javascript 复制代码
const { URL, URLSearchParams } = require('url');

// 1. 解析 URL
function parseURL(urlString) {
  try {
    const url = new URL(urlString);
    return {
      protocol: url.protocol,
      hostname: url.hostname,
      port: url.port,
      pathname: url.pathname,
      search: url.search,
      hash: url.hash,
      username: url.username,
      password: url.password,
      origin: url.origin
    };
  } catch (error) {
    console.error('URL 解析错误:', error);
    return null;
  }
}

// 2. 构建 URL
function buildURL(options) {
  const url = new URL('https://example.com');
  
  if (options.protocol) url.protocol = options.protocol;
  if (options.hostname) url.hostname = options.hostname;
  if (options.port) url.port = options.port;
  if (options.pathname) url.pathname = options.pathname;
  if (options.search) url.search = options.search;
  if (options.hash) url.hash = options.hash;
  if (options.username) url.username = options.username;
  if (options.password) url.password = options.password;
  
  return url.toString();
}

// 3. 解析查询字符串
function parseQueryString(queryString) {
  const params = new URLSearchParams(queryString);
  const result = {};
  
  for (const [key, value] of params) {
    result[key] = value;
  }
  
  return result;
}

// 4. 构建查询字符串
function buildQueryString(params) {
  const searchParams = new URLSearchParams();
  
  for (const [key, value] of Object.entries(params)) {
    searchParams.append(key, value);
  }
  
  return searchParams.toString();
}

4. URL 验证和规范化

javascript 复制代码
const { URL } = require('url');

// 1. 验证 URL
function isValidURL(urlString) {
  try {
    new URL(urlString);
    return true;
  } catch (error) {
    return false;
  }
}

// 2. 规范化 URL
function normalizeURL(urlString) {
  try {
    const url = new URL(urlString);
    
    // 移除默认端口
    if (url.port === '80' && url.protocol === 'http:') {
      url.port = '';
    }
    if (url.port === '443' && url.protocol === 'https:') {
      url.port = '';
    }
    
    // 规范化路径
    url.pathname = url.pathname.replace(/\/+/g, '/');
    if (url.pathname !== '/' && url.pathname.endsWith('/')) {
      url.pathname = url.pathname.slice(0, -1);
    }
    
    return url.toString();
  } catch (error) {
    return urlString;
  }
}

// 3. 解析相对 URL
function resolveURL(base, relative) {
  try {
    return new URL(relative, base).toString();
  } catch (error) {
    return null;
  }
}

// 4. 提取 URL 组件
function extractURLComponents(urlString) {
  try {
    const url = new URL(urlString);
    return {
      protocol: url.protocol.replace(':', ''),
      domain: url.hostname,
      port: url.port || (url.protocol === 'https:' ? '443' : '80'),
      path: url.pathname,
      query: url.search.slice(1),
      hash: url.hash.slice(1)
    };
  } catch (error) {
    return null;
  }
}

5. URL 编码和解码

javascript 复制代码
const { URL, URLSearchParams } = require('url');

// 1. URL 编码
function encodeURL(urlString) {
  try {
    const url = new URL(urlString);
    return url.toString();
  } catch (error) {
    return encodeURI(urlString);
  }
}

// 2. URL 解码
function decodeURL(urlString) {
  try {
    return decodeURI(urlString);
  } catch (error) {
    return urlString;
  }
}

// 3. 参数编码
function encodeParams(params) {
  const searchParams = new URLSearchParams();
  
  for (const [key, value] of Object.entries(params)) {
    searchParams.append(key, value);
  }
  
  return searchParams.toString();
}

// 4. 参数解码
function decodeParams(queryString) {
  const params = new URLSearchParams(queryString);
  const result = {};
  
  for (const [key, value] of params) {
    result[key] = value;
  }
  
  return result;
}

6. URL 操作工具

javascript 复制代码
const { URL, URLSearchParams } = require('url');

// 1. URL 合并
function mergeURLs(base, relative) {
  try {
    return new URL(relative, base).toString();
  } catch (error) {
    return null;
  }
}

// 2. URL 比较
function compareURLs(url1, url2) {
  try {
    const u1 = new URL(url1);
    const u2 = new URL(url2);
    
    return {
      sameProtocol: u1.protocol === u2.protocol,
      sameHost: u1.host === u2.host,
      samePath: u1.pathname === u2.pathname,
      sameQuery: u1.search === u2.search,
      sameHash: u1.hash === u2.hash,
      isEqual: u1.href === u2.href
    };
  } catch (error) {
    return null;
  }
}

// 3. URL 转换
function transformURL(urlString, options) {
  try {
    const url = new URL(urlString);
    
    if (options.protocol) url.protocol = options.protocol;
    if (options.hostname) url.hostname = options.hostname;
    if (options.port) url.port = options.port;
    if (options.pathname) url.pathname = options.pathname;
    if (options.search) url.search = options.search;
    if (options.hash) url.hash = options.hash;
    
    return url.toString();
  } catch (error) {
    return null;
  }
}

// 4. URL 验证器
class URLValidator {
  constructor(options = {}) {
    this.options = {
      protocols: ['http:', 'https:'],
      requireProtocol: true,
      ...options
    };
  }
  
  validate(urlString) {
    try {
      const url = new URL(urlString);
      
      if (this.options.requireProtocol && !url.protocol) {
        return false;
      }
      
      if (this.options.protocols && !this.options.protocols.includes(url.protocol)) {
        return false;
      }
      
      return true;
    } catch (error) {
      return false;
    }
  }
}

7. 实际应用示例

javascript 复制代码
const { URL, URLSearchParams } = require('url');

// 1. URL 路由解析器
class URLRouter {
  constructor() {
    this.routes = new Map();
  }
  
  addRoute(pattern, handler) {
    this.routes.set(pattern, handler);
  }
  
  match(urlString) {
    const url = new URL(urlString);
    const pathname = url.pathname;
    
    for (const [pattern, handler] of this.routes) {
      const regex = new RegExp(pattern);
      if (regex.test(pathname)) {
        return {
          handler,
          params: this.extractParams(pattern, pathname),
          query: Object.fromEntries(url.searchParams)
        };
      }
    }
    
    return null;
  }
  
  extractParams(pattern, pathname) {
    const params = {};
    const patternParts = pattern.split('/');
    const pathParts = pathname.split('/');
    
    for (let i = 0; i < patternParts.length; i++) {
      if (patternParts[i].startsWith(':')) {
        const paramName = patternParts[i].slice(1);
        params[paramName] = pathParts[i];
      }
    }
    
    return params;
  }
}

// 2. URL 参数处理器
class URLParamHandler {
  constructor() {
    this.params = new URLSearchParams();
  }
  
  setParams(params) {
    for (const [key, value] of Object.entries(params)) {
      this.params.set(key, value);
    }
  }
  
  getParams() {
    return Object.fromEntries(this.params);
  }
  
  removeParam(key) {
    this.params.delete(key);
  }
  
  clearParams() {
    this.params = new URLSearchParams();
  }
  
  toString() {
    return this.params.toString();
  }
}

// 3. URL 重写器
class URLRewriter {
  constructor(rules) {
    this.rules = rules;
  }
  
  rewrite(urlString) {
    const url = new URL(urlString);
    
    for (const rule of this.rules) {
      if (rule.pattern.test(url.pathname)) {
        url.pathname = url.pathname.replace(rule.pattern, rule.replacement);
      }
    }
    
    return url.toString();
  }
}

// 4. URL 监控器
class URLMonitor {
  constructor() {
    this.history = new Map();
  }
  
  track(urlString) {
    const url = new URL(urlString);
    const key = url.origin + url.pathname;
    
    if (!this.history.has(key)) {
      this.history.set(key, {
        count: 0,
        lastAccess: null,
        params: new Map()
      });
    }
    
    const entry = this.history.get(key);
    entry.count++;
    entry.lastAccess = new Date();
    
    for (const [key, value] of url.searchParams) {
      if (!entry.params.has(key)) {
        entry.params.set(key, new Set());
      }
      entry.params.get(key).add(value);
    }
  }
  
  getStats() {
    const stats = [];
    
    for (const [url, data] of this.history) {
      stats.push({
        url,
        count: data.count,
        lastAccess: data.lastAccess,
        params: Object.fromEntries(
          Array.from(data.params.entries()).map(([key, values]) => [
            key,
            Array.from(values)
          ])
        )
      });
    }
    
    return stats;
  }
}

URL 模块的主要特点:

  1. 提供 URL 解析和构建功能
  2. 支持查询参数处理
  3. 提供 URL 编码和解码
  4. 支持 URL 验证和规范化
  5. 提供 URL 组件提取和操作

使用建议:

  1. 使用 URL 类处理 URL 字符串
  2. 使用 URLSearchParams 处理查询参数
  3. 注意 URL 编码和解码
  4. 验证 URL 格式
  5. 规范化 URL 路径和参数
相关推荐
codingWhat1 天前
能效平台设计方案(打通gitlab和飞书)
后端·node.js·koa
见过夏天3 天前
Node.js 常用命令全攻略
node.js
前端双越老师3 天前
我从 0 开发的 AI Agent 智语项目发布了
前端·node.js·agent
kyriewen4 天前
2026 年了,还在用 Node.js?Bun 迁移实战:20 分钟搞定,附踩坑记录
前端·javascript·node.js
donecoding4 天前
3 条命令搞定闭环 Monorepo:Lerna 版本管理 + 拓扑构建 + 自定义分发
前端·前端框架·node.js
Flynt5 天前
npm v12 来了:allowScripts 默认关闭,我的项目差点跑不起来
安全·npm·node.js
叫我Paul就好6 天前
尝试 Node 搭建后端-开发框架
node.js
风止何安啊8 天前
网课倍速痛点解决:一套前端代码实现自由控速播放器
前端·javascript·node.js
糖拌西瓜皮8 天前
Node.js核心模块实战:文件、路径、HTTP与流处理
javascript·node.js
糖拌西瓜皮8 天前
Node.js工程化实践:包管理、TypeScript配置与代码质量
typescript·node.js