前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket

# 网络地址解析 url

30 秒速记

  • Node 里有两套 URL 解析:老的 url.parse()(legacy,已废弃)和标准的 new URL()(WHATWG,和浏览器一致)
  • 新代码一律用 new URL(input, base),非法输入直接抛 TypeError,不会默默给你一个半残的对象
  • 取参数用 url.searchParams.get('k'),自动解码
  • 分清 origin / host / hostname / pathname,安全校验比对 hostname,别用 includes
  • 外部 URL 还要限制协议、端口、凭据和最终解析出来的 IP,防 SSRF

Node 里解析 URL 现在就用全局的 new URL(),它和浏览器是同一套 WHATWG 标准,老的 url.parse() 官方已经标记废弃了。 老接口的问题是太宽松,畸形地址也能解析出个结果,而且和浏览器的解析规则不一致,历史上出过好几次主机名混淆导致的安全问题。new URL() 遇到非法输入直接抛 TypeError,参数用 searchParams 取,自动解码。做跳转白名单、SSRF 防护时,一定拿解析后的 hostname 精确比对,url.includes('trusted.com') 这种写法碰到 trusted.com.evil.io 就破了。

理解「网络地址解析 url」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 network 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

老接口和新接口对比一下:

const url = require('url');

// 老接口:url.parse,宽松、已废弃
const a = url.parse('http://user:pw@example.com:8080/p?a=1#h', true);
console.log(a.hostname, a.query.a); // example.com 1

// 新接口:WHATWG URL,全局可用,和浏览器一致
const b = new URL('http://user:pw@example.com:8080/p?a=1#h');
console.log(b.hostname);              // example.com
console.log(b.searchParams.get('a')); // '1'
console.log(b.origin);                // http://example.com:8080

// 非法输入:新接口直接报错
try { new URL('not a url'); } catch (e) { console.log(e.code); } // ERR_INVALID_URL
@前端进阶之旅: 代码已经复制到剪贴板

几个容易混的字段:host 带端口(example.com:8080),hostname 不带;origin 是协议加主机加端口,跨域判断用它;pathname 只有路径;search 带问号,searchParams 是可操作的对象。

官方文档已经把 url.parse() 列为废弃(DEP0169),原因是它对某些畸形主机名的解析和浏览器不一致,可能被用来绕过安全校验。url.format() 还能用,而且可以直接接收 URL 对象。

面试官追问

追问 1跳转白名单写的是 target.includes('mysite.com'),有什么问题?
参考回答

https://mysite.com.evil.io 和 https://evil.io/?mysite.com 都能过。要 new URL(target).hostname === 'mysite.com',或者精确匹配后缀 .mysite.com。

追问 2new URL('/a/b') 为什么报错?
参考回答

相对地址没有基准没法解析,要传第二个参数:new URL('/a/b', 'https://example.com')。只是想判断能不能解析,Node 19.9 起可以用 URL.canParse(input, base),不用 try/catch。

追问 3服务端要请求用户提交的图片地址,除了解析成功还要校验什么?
参考回答

协议只放 https:,拒绝带 username / password 的地址,端口限制在白名单,再把 hostname 解析出的 IP 和内网段比对。跟随重定向时每一跳都要重新校验,不然一个 302 就跳进内网了。

追问 4老项目到处是 url.parse(),要不要一次性全换掉?
参考回答

涉及安全判断的地方(白名单、代理、SSRF 校验)优先换;纯展示的可以慢慢迁。注意两者对畸形输入的行为不同,迁移时要补异常输入的测试。

# 模块概述

30 秒速记

  • url 模块老三件套:parse(字符串 → 对象)、format(对象 → 字符串)、resolve(相对地址拼成绝对地址)
  • 这三个都属于 legacy API,新代码用全局 URL 和 URLSearchParams
  • 还有几个实用工具:url.fileURLToPath()、url.pathToFileURL(),ESM 里拿 __dirname 常用
  • 解析成功 ≠ 地址合法,业务校验要单独做

url 模块就是把 URL 字符串拆成好操作的结构,或者反过来拼回去,老 API 一共三个方法:parse、format、resolve。 这几个在老项目里非常常见,但现在官方推荐用全局的 URL 类,它是 WHATWG 标准,和浏览器行为一致,拼参数也有 URLSearchParams。url 模块里现在最常用的反而是 fileURLToPath,在 ESM 里 fileURLToPath(import.meta.url) 就能拿到当前文件路径。不管用哪套,拆出来结构只是第一步,地址是否允许访问还得业务自己校验。

nodejs中,提供了url这个非常实用的模块,用来做URL的解析。在做node服务端的开发时会经常用到。使用很简单,总共只有3个方法。

理解「模块概述」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 module 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

面试官追问

追问 1能被 url.parse() 解析出对象,是不是就说明链接合法?
参考回答

不是。url.parse 非常宽松,畸形字符串也能给你一个对象,只是字段缺一块。合法性要另外校验:协议、hostname、白名单,这些都不是解析器的职责。

追问 2ESM 里没有 __dirname,怎么拿当前文件所在目录?
参考回答

path.dirname(fileURLToPath(import.meta.url)),fileURLToPath 从 url 模块里导入。Node 20.11 起也可以直接用 import.meta.dirname。

追问 3拼查询参数,手写字符串和用 URLSearchParams 有区别吗?
参考回答

手写容易漏编码,参数里有 &、=、中文就坏了。new URLSearchParams({ q: 'a&b' }).toString() 会得到 q=a%26b,编码自动处理。

追问 4团队想封装一个统一的 URL 工具,底层选 url.parse 还是 URL?
参考回答

选 URL。行为跟浏览器一致,非法输入抛错,前后端同构代码也能共用;url.parse 是废弃接口,新封装没理由再基于它。

# 模块方法概述

30 秒速记

  • url.parse(str):字符串 → 对象,读写字段方便
  • url.format(obj):对象 → 字符串,parse 的反向操作,也接受 URL 对象
  • url.resolve(from, to):以 from 为基准把 to 解析成完整地址,规则和浏览器点链接一样
  • resolve 的坑:from 末尾有没有 / 结果不同,to 以 / 开头会替换整个路径
  • 新写法:url.resolve(from, to) ≈ new URL(to, from).href

三个方法分别管「拆开」「拼回」「相对转绝对」。 parse 把字符串变对象,format 反过来;resolve 最容易答错,它的规则和浏览器里点一个相对链接一模一样:url.resolve('http://a.com/one/two', 'three') 得到 http://a.com/one/three,因为 two 被当成文件名替换掉了;基准写成 /one/two/ 才会得到 /one/two/three;to 以 / 开头就直接从根路径开始。新代码里同样的效果写成 new URL(to, from).href。

url模块三个方法分别是:

  • .parse(urlString):将url字符串,解析成object,便于开发者进行操作。
  • .format(urlObj):.parse() 方法的反向操作。
  • .resove(from, to):以from作为起始地址,解析出完整的目标地址(还是看直接看例子好些)

url.resolve

基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
      • 模块概述
      • 模块方法概述
      • url解析:url.parse()
        • 例子1:参数值不进行解析
        • 例子2:对参数值进行decode
        • 例子3:针对路径 //foo/bar 的处理
      • 关于urlObject
      • url拼接:url.format(urlObject)
      • url.resolve(from, to)
      • 非法字符转义
      • 相关链接
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket
完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

网络地址解析 url|Nodejs专题系列

# 网络地址解析 url

30 秒速记

  • Node 里有两套 URL 解析:老的 url.parse()(legacy,已废弃)和标准的 new URL()(WHATWG,和浏览器一致)
  • 新代码一律用 new URL(input, base),非法输入直接抛 TypeError,不会默默给你一个半残的对象
  • 取参数用 url.searchParams.get('k'),自动解码
  • 分清 origin / host / hostname / pathname,安全校验比对 hostname,别用 includes
  • 外部 URL 还要限制协议、端口、凭据和最终解析出来的 IP,防 SSRF

Node 里解析 URL 现在就用全局的 new URL(),它和浏览器是同一套 WHATWG 标准,老的 url.parse() 官方已经标记废弃了。 老接口的问题是太宽松,畸形地址也能解析出个结果,而且和浏览器的解析规则不一致,历史上出过好几次主机名混淆导致的安全问题。new URL() 遇到非法输入直接抛 TypeError,参数用 searchParams 取,自动解码。做跳转白名单、SSRF 防护时,一定拿解析后的 hostname 精确比对,url.includes('trusted.com') 这种写法碰到 trusted.com.evil.io 就破了。

理解「网络地址解析 url」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 network 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

老接口和新接口对比一下:

const url = require('url');

// 老接口:url.parse,宽松、已废弃
const a = url.parse('http://user:pw@example.com:8080/p?a=1#h', true);
console.log(a.hostname, a.query.a); // example.com 1

// 新接口:WHATWG URL,全局可用,和浏览器一致
const b = new URL('http://user:pw@example.com:8080/p?a=1#h');
console.log(b.hostname);              // example.com
console.log(b.searchParams.get('a')); // '1'
console.log(b.origin);                // http://example.com:8080

// 非法输入:新接口直接报错
try { new URL('not a url'); } catch (e) { console.log(e.code); } // ERR_INVALID_URL
@前端进阶之旅: 代码已经复制到剪贴板

几个容易混的字段:host 带端口(example.com:8080),hostname 不带;origin 是协议加主机加端口,跨域判断用它;pathname 只有路径;search 带问号,searchParams 是可操作的对象。

官方文档已经把 url.parse() 列为废弃(DEP0169),原因是它对某些畸形主机名的解析和浏览器不一致,可能被用来绕过安全校验。url.format() 还能用,而且可以直接接收 URL 对象。

面试官追问

追问 1跳转白名单写的是 target.includes('mysite.com'),有什么问题?
参考回答

https://mysite.com.evil.io 和 https://evil.io/?mysite.com 都能过。要 new URL(target).hostname === 'mysite.com',或者精确匹配后缀 .mysite.com。

追问 2new URL('/a/b') 为什么报错?
参考回答

相对地址没有基准没法解析,要传第二个参数:new URL('/a/b', 'https://example.com')。只是想判断能不能解析,Node 19.9 起可以用 URL.canParse(input, base),不用 try/catch。

追问 3服务端要请求用户提交的图片地址,除了解析成功还要校验什么?
参考回答

协议只放 https:,拒绝带 username / password 的地址,端口限制在白名单,再把 hostname 解析出的 IP 和内网段比对。跟随重定向时每一跳都要重新校验,不然一个 302 就跳进内网了。

追问 4老项目到处是 url.parse(),要不要一次性全换掉?
参考回答

涉及安全判断的地方(白名单、代理、SSRF 校验)优先换;纯展示的可以慢慢迁。注意两者对畸形输入的行为不同,迁移时要补异常输入的测试。

# 模块概述

30 秒速记

  • url 模块老三件套:parse(字符串 → 对象)、format(对象 → 字符串)、resolve(相对地址拼成绝对地址)
  • 这三个都属于 legacy API,新代码用全局 URL 和 URLSearchParams
  • 还有几个实用工具:url.fileURLToPath()、url.pathToFileURL(),ESM 里拿 __dirname 常用
  • 解析成功 ≠ 地址合法,业务校验要单独做

url 模块就是把 URL 字符串拆成好操作的结构,或者反过来拼回去,老 API 一共三个方法:parse、format、resolve。 这几个在老项目里非常常见,但现在官方推荐用全局的 URL 类,它是 WHATWG 标准,和浏览器行为一致,拼参数也有 URLSearchParams。url 模块里现在最常用的反而是 fileURLToPath,在 ESM 里 fileURLToPath(import.meta.url) 就能拿到当前文件路径。不管用哪套,拆出来结构只是第一步,地址是否允许访问还得业务自己校验。

nodejs中,提供了url这个非常实用的模块,用来做URL的解析。在做node服务端的开发时会经常用到。使用很简单,总共只有3个方法。

理解「模块概述」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 module 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

面试官追问

追问 1能被 url.parse() 解析出对象,是不是就说明链接合法?
参考回答

不是。url.parse 非常宽松,畸形字符串也能给你一个对象,只是字段缺一块。合法性要另外校验:协议、hostname、白名单,这些都不是解析器的职责。

追问 2ESM 里没有 __dirname,怎么拿当前文件所在目录?
参考回答

path.dirname(fileURLToPath(import.meta.url)),fileURLToPath 从 url 模块里导入。Node 20.11 起也可以直接用 import.meta.dirname。

追问 3拼查询参数,手写字符串和用 URLSearchParams 有区别吗?
参考回答

手写容易漏编码,参数里有 &、=、中文就坏了。new URLSearchParams({ q: 'a&b' }).toString() 会得到 q=a%26b,编码自动处理。

追问 4团队想封装一个统一的 URL 工具,底层选 url.parse 还是 URL?
参考回答

选 URL。行为跟浏览器一致,非法输入抛错,前后端同构代码也能共用;url.parse 是废弃接口,新封装没理由再基于它。

# 模块方法概述

30 秒速记

  • url.parse(str):字符串 → 对象,读写字段方便
  • url.format(obj):对象 → 字符串,parse 的反向操作,也接受 URL 对象
  • url.resolve(from, to):以 from 为基准把 to 解析成完整地址,规则和浏览器点链接一样
  • resolve 的坑:from 末尾有没有 / 结果不同,to 以 / 开头会替换整个路径
  • 新写法:url.resolve(from, to) ≈ new URL(to, from).href

三个方法分别管「拆开」「拼回」「相对转绝对」。 parse 把字符串变对象,format 反过来;resolve 最容易答错,它的规则和浏览器里点一个相对链接一模一样:url.resolve('http://a.com/one/two', 'three') 得到 http://a.com/one/three,因为 two 被当成文件名替换掉了;基准写成 /one/two/ 才会得到 /one/two/three;to 以 / 开头就直接从根路径开始。新代码里同样的效果写成 new URL(to, from).href。

url模块三个方法分别是:

  • .parse(urlString):将url字符串,解析成object,便于开发者进行操作。
  • .format(urlObj):.parse() 方法的反向操作。
  • .resove(from, to):以from作为起始地址,解析出完整的目标地址(还是看直接看例子好些)

url.resolve 的规则用几个例子一次看明白:

const url = require('url');

url.resolve('http://a.com/one/two', 'three');   // 'http://a.com/one/three'
url.resolve('http://a.com/one/two/', 'three');  // 'http://a.com/one/two/three'
url.resolve('http://a.com/one/two', '/three');  // 'http://a.com/three'
url.resolve('http://a.com/one/two', '../x');    // 'http://a.com/x'
url.resolve('http://a.com/one', 'http://b.com');// 'http://b.com/'

// 等价的新写法
new URL('three', 'http://a.com/one/two').href;  // 'http://a.com/one/three'
@前端进阶之旅: 代码已经复制到剪贴板

记忆方法:把 from 想成浏览器当前打开的页面地址,to 是页面里一个 <a href> 的值,点下去跳到哪,resolve 就返回什么。基准末尾没有 / 时最后一段是「文件」,会被替换;有 / 时是「目录」,会在后面追加。

format 是 parse 的反向操作,比如 url.format({ protocol: 'https', hostname: 'a.com', pathname: '/p', query: { q: 1 } }) 得到 https://a.com/p?q=1。它也能直接接收 URL 对象,并通过 { auth: false, search: false } 这类选项去掉对应部分。

← 4.9 域名解析 dns5.1 URL查询字符串 querystring →

fe