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 路径和参数
相关推荐
阿黎梨梨16 小时前
AI也有记忆?LangChain Memory 管理指南
langchain·node.js·llm
小小龙学IT18 小时前
libuv 开源异步 I/O 事件循环库深度解析:Node.js 的心脏,C++ 高性能网络程序的引擎
c++·开源·node.js
用户672465366052 天前
Node 守护进程日志转发踩坑记:stdio 管道、UTF-8 截断,和一个字符串按值传参的故事
node.js
coderCN2 天前
Nodejs express+knex(ORM框架)
前端·node.js
coderCN2 天前
Nodejs mysql2+express+yaml
node.js
烬羽2 天前
我把"时间胶囊"部署上腾讯云宝塔,跨域从根源消失了
nginx·node.js·全栈
东风破_2 天前
danci 2:创建的单词书到底存在哪里?从 Supabase 一路理解 ORM、Drizzle 和 RLS
数据库·后端·node.js
东风破_2 天前
danci 项目(三):从 JSON 数据到 AI Coding,真实项目里的数据清洗、Prompt 和工程规范
前端·后端·node.js
东风破_2 天前
danci 项目(一):从需求到架构,一个单词学习系统为什么会这样设计
前端·后端·node.js
__zRainy__2 天前
Node系列 · Express:常用的中间件
中间件·node.js·express