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 路径和参数
相关推荐
前端双越老师2 小时前
前端开发 AI Agent 智能体,需要掌握哪些知识?
前端·node.js·agent
EndingCoder2 小时前
Electron 安全性最佳实践:防范常见漏洞
前端·javascript·electron·前端框架·node.js·桌面端
醉方休11 小时前
npm/pnpm软链接的优点和使用场景
前端·npm·node.js
一支鱼12 小时前
基于 Node.js 的短视频制作神器 ——FFCreator
前端·node.js·音视频开发
龙潜月七12 小时前
Joplin-解决 Node.js 中 “digital envelope routines::unsupported“ 错误
node.js
不知名raver(学python版)1 天前
npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR!
前端·npm·node.js
惜.己2 天前
针对nvm不能导致npm和node生效的解决办法
前端·npm·node.js
上单带刀不带妹2 天前
Node.js 的模块化规范是什么?CommonJS 和 ES6 模块有什么区别?
前端·node.js·es6·模块化
cdcdhj2 天前
数据库存储大量的json文件怎么样高效的读取和分页,利用文件缓存办法不占用内存
缓存·node.js·json
HWL56792 天前
在本地使用Node.js和Express框架来连接和操作远程数据库
node.js·express