JavaScript 中 URL 和 URLSearchParams 的陷阱

javascript 中 url 和 urlsearchparams 的陷阱

一切都始于一个错误

在 javascript 和 node.js 中使用 url 应该很简单,但是我们项目中最近的一个错误让我陷入了 url 和 urlsearchparams api 中微妙怪癖的兔子洞。这篇文章将探讨这些怪癖,它们如何在您的代码中引起问题,以及您可以采取哪些措施来避免它们。

问题:使用 axios 处理 url

我们在生成 url 并向其添加哈希签名时遇到了此问题。查询参数的百分比编码不一致,导致意外行为和错误的哈希签名。

很明显,url 和 urlsearchparams 对象之间的交互需要格外小心。

陷阱#1:url.search 与 urlsearchparams.tostring()

第一个惊喜是 url.search 和 urlsearchparams.tostring() 之间的区别。

立即学习“Java免费学习笔记(深入)”;

使用 .searchparams 修改 url 时要小心,因为根据 whatwg 规范,urlsearchparams 对象使用不同的规则来确定要对哪些字符进行百分比编码。例如,url 对象不会对 ascii 波形符 (~) 字符进行百分号编码,而 urlsearchparams 将始终对其进行编码。

// example 1const url = new url("https://example.com?param=foo bar");console.log(url.search); // prints param=foo%20barconsole.log(url.searchparams.tostring()); // prints ?param=foo+bar// example 2const myurl = new url('https://example.org/abc?foo=~bar');console.log(myurl.search);  // prints ?foo=~bar// modify the url via searchparams...myurl.searchparams.sort();console.log(myurl.search);  // prints ?foo=%7ebar

登录后复制

在我们的项目中,我们需要显式地重新分配 url.search = url.searchparams.tostring() 以确保查询字符串的编码一致。

陷阱#2:加号困境

另一个问题是 urlsearchparams 如何处理 字符。默认情况下,urlsearchparams 将 解释为空格,这在编码二进制数据或 base64 字符串时可能会导致数据损坏。

const params = new urlsearchparams("bin=e+axqb+a");console.log(params.get("bin")); // "e axqb a"

登录后复制

一种解决方案是在将值附加到 urlsearchparams 之前使用encodeuricomponent:

params.append("bin", encodeuricomponent("e+axqb+a"));

登录后复制

更多详细信息请参阅 mdn 文档。

陷阱 #3:urlsearchparams.get 与 urlsearchparams.tostring()

比较 urlsearchparams.get 和 urlsearchparams.tostring 的输出时会出现另一个微妙之处。例如:

const params = new urlsearchparams("?key=value&key=other");console.log(params.get("key")); // "value" (first occurrence)console.log(params.tostring()); // "key=value&key=other" (all occurrences serialized)

登录后复制

在多值场景中,get 仅返回第一个值,而 tostring 则序列化所有值。

我们代码库中的修复

在我们的项目中,我们通过显式重新分配搜索属性解决了该问题:

url.search = url.searchparams.tostring();url.searchparams.set(  "hash",  cryptography.createsha256hmacbase64urlsafe(url.href, secret_key ?? ""));

登录后复制

这确保了在添加哈希值之前所有查询参数都已正确编码。

node.js 查询字符串模块

whatwg urlsearchparams 接口和 querystring 模块具有类似的用途,但 querystring 模块的用途更通用,因为它允许自定义分隔符(& 和 =)。另一方面,urlsearchparams api 纯粹是为 url 查询字符串而设计的。

querystring 比 urlsearchparams 性能更高,但不是标准化 api。当性能不重要或需要与浏览器代码兼容时,请使用 urlsearchparams。

与 querystring 模块不同,使用 urlsearchparams 时,不允许数组值形式的重复键。数组使用 array.tostring() 进行字符串化,它只是用逗号连接所有数组元素。

const params = new urlsearchparams({  user: 'abc',  query: ['first', 'second'],});console.log(params.getall('query'));// prints [ 'first,second' ]console.log(params.tostring());// prints 'user=abc&query=first%2csecond'

登录后复制

使用querystring模块,查询字符串’foo=bar&abc=xyz&abc=123’被解析为:

{  "foo": "bar",  "abc": ["xyz", "123"]}

登录后复制

要点

小心 urlsearchparams 处理特殊字符(例如 ~)和空格。必要时使用encodeuricomponent。

了解 url.search、urlsearchparams.get 和 urlsearchparams.tostring 之间的区别,以避免意外行为。

在 node.js 中,如果要将重复的查询参数键解析为数组,请使用查询字符串模块。

以上就是JavaScript 中 URL 和 URLSearchParams 的陷阱的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2648592.html

(0)
上一篇 2025年3月7日 08:15:06
下一篇 2025年3月7日 08:15:16

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 多任务处理和并行性|第 1 部分

    多任务和并行是计算和编程中经常使用的相关但不同的概念。这是一个明显的区别: 多任务处理 定义:多任务处理是指系统通过快速切换来看似同时处理多个任务(进程或线程)的能力。 工作原理: 任务共享相同的CPU或资源。 操作系统使用时间切片在任务之…

    2025年3月7日
    200
  • NodeJS模块【简单说明】

    什么是模块? 假设您的 nodejs 项目中有一个 index.js 文件,您在其中使用了五个函数。但是,其中两个函数也可能在其他文件中使用。因此,您在项目中创建了三个文件,而不是一个文件: index.jsdependency1.jsde…

    2025年3月7日
    200
  • Redux 与 Zustand:综合比较

    react 状态管理概述 redux(详细说明): 建筑学: store:整个应用程序的中央状态持有者操作:状态更改的事件reducer:创建新状态的纯函数 复杂: 重要的样板代码陡峭的学习曲线支持 redux thunk、redux sa…

    2025年3月7日
    200
  • JavaScript 中的“this”关键字到底是什么?

    关键见解: 全局范围:在全局上下文中,this 指的是全局对象(例如,窗口)。 函数上下文:在常规函数中,这在严格和非严格模式下表现不同,返回未定义或全局对象。 方法:在对象方法中,this 指对象本身,允许访问其属性。 调用、应用、绑定:…

    2025年3月7日
    200
  • 同步与异步 JavaScript 简化

    javascript 被广泛认为是一种单线程语言。这意味着它一次只能按一个顺序执行一段代码。然而,javascript 高效处理异步任务的能力是其强大的构建交互式和响应式应用程序的原因之一。 在本文中,我们将通过实际示例探讨同步和异步 ja…

    2025年3月7日
    200
  • 从 JS 角度初看 C#

    我的旅程开始于…… 当我开始创建一个项目时,我的目标是构建一款可能具有 3d 元素、具有交互性、特别是在移动平台上玩的游戏。我还想将人工智能集成到游戏中以增加深度和复杂性。自然地,这促使我探索 c#——unity 游戏引擎中常用的一种语言。…

    2025年3月7日
    200
  • 提升:面向颞死区

    所以,也许您正在考虑 var 与 let 和 const 之间的基本区别:“const 仅用于读取,let 是可变的,而 var 两者都是”,唯一的区别是 es6 引入了 const 和 let,并且var 是一个老式语法。嗯,一点也不。 …

    2025年3月7日
    200
  • Remix 与 Nextjs:为什么选择 Remix?

    简介Remix 和 Next.js 都是构建现代 Web 应用程序的流行框架,但它们具有不同的设计理念。虽然 Next.js 因其灵活性和混合渲染模型而被广泛使用,但 Remix 因其性能优化、开发人员友好的方法以及对服务器优先渲染的重视而…

    2025年3月7日
    200
  • typescript 类和接口

    TypeScript中的类定义对象模板,包括属性和方法;而接口定义对象合同,规定必须具备的属性和方法。两者主要区别:类创建实际对象,接口定义对象合同;类有构造函数和方法,接口仅有属性和方法声明;接口可继承接口,类只能继承类;根据实际需要选择…

    2025年3月7日
    200
  • 关于useEffect错误用法的推理

    React 中最错误使用的 hook 无疑是 useEffect。我们这样做有多种原因,而不仅仅是一个。让我们从我的角度来探讨其中的每一个。 生命周期遗产 所以我认为影响更大的原因之一是,在前钩子时代,我们使用了类。对于这一时期开始使用Re…

    2025年3月7日
    200

发表回复

登录后才能评论