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 的输出时会出现另一个微妙之处。例如:

百度文心百中 百度文心百中

百度大模型语义搜索体验中心

百度文心百中 22 查看详情 百度文心百中

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 的陷阱的详细内容,更多请关注创想鸟其它相关文章!

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

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月6日 18:19:55
下一篇 2025年11月6日 18:21:37

相关推荐

  • 使用 PyInstaller 生成的可视化程序中,如何防止 ffmpeg 转换 mp3 格式音频时出现命令窗口?

    在 [python] pyinstaller 生成可视化界面,ffmpeg 转换音频运行 subprocess.run() 有命令窗口弹出 的问题中,使用 pyinstaller 生成了可视化界面的 exe 程序后,调用 ffmpeg 进行音频转换时,会出现命令窗口弹出。 问题中 使用了 subpr…

    2025年12月13日
    000
  • 理解 Python 中的字符串 | Day 天蟒

    第 8 天:python 中的用户输入 | 100 天 python 在 python 中,字符串作为一种数据类型发挥着至关重要的作用,它允许您处理文本数据。在本博客中,我们将探讨字符串的基础知识、创建字符串的不同方法以及多行字符串、索引和循环字符串中的字符等高级概念。本指南将使您对字符串有深入的了…

    2025年12月13日
    000
  • Python 中的函数参数类型:关键字参数、可变参数和动态参数有什么区别?

    python 中的关键字参数、可变参数和动态参数 在 python 中,函数调用时可以传递不同类型的参数,包括关键字参数、可变参数和动态参数。 关键字参数 关键字参数以键值对的形式传递,通过变量名来指定参数值。它们必须在调用函数时显式指定。例如: 立即学习“Python免费学习笔记(深入)”; de…

    2025年12月13日
    000
  • JS 开发人员的 Python 基础知识

    1.基本语法和数据类型 变量声明:不需要 var、let 或 const。只需命名变量即可。 x = 10 name = “python” 原始类型: int(整数)浮动(浮点)str(字符串)布尔(布尔值) 数据结构: 列表(就像 js 中的数组): numbers = [1, 2, 3] num…

    2025年12月13日
    000
  • 在 PyTorch 中展开

    请我喝杯咖啡☕ *备忘录: 我的帖子解释了 unflatten()。我的帖子解释了 flatten() 和 ravel()。我的帖子解释了 flatten()。 unflatten() 可以向零个或多个元素的一维或多个 d 张量添加零个或多个维度,得到零个或多个元素的一维或多个 d 张量,如下所示:…

    2025年12月13日
    000
  • 在 PyTorch 中展平

    请我喝杯咖啡☕ *备忘录: 我的帖子解释了 flatten() 和 ravel()。我的帖子解释了 unflatten()。 flatten() 可以通过从零个或多个元素的 0d 或多个 d 张量中选择维度来移除零个或多个维度,得到零个或多个元素的 1d 或多个 d 张量,如下所示: *备忘录: 初…

    2025年12月13日
    000
  • 到 Django 还是 DjangoREST?

    Django 和 DjangoREST 是 Python 中的高级框架,可能会争论它们是否不同,所以它们是吗? DjangoREST 用于构建 API(应用程序编程接口),而 Django 用于 Web 应用程序。尽管如此,我们还是会得出结论,所以让我们进一步探索。姜戈是什么?它是一个遵循模型-视图…

    2025年12月13日
    000
  • Mastering Python’s __name__ and __main__: Understanding Script Execution and Module Imports

    介绍 python 的 name 和 main 是两个经常被误解的概念,它们在脚本的执行方式和模块的导入方式中发挥着至关重要的作用。在这篇文章中,我们将详细解释 name 和 main 的实际含义、它们为何如此重要,以及如何利用它们来编写更加模块化、可测试和可重用的代码。最后,您将熟悉这个基本概念,…

    2025年12月13日
    000
  • Migrar de SQLite a MySQL

    我自我介绍一下,我是 alfredo riveros,我已经学习编程多年了,我目前正在 río tercero 高等商学院学习软件开发高级技术员,下面我将描述我面临的挑战遇到了。 正如标题所说,我的目标是将 SQLite 数据库迁移到 MySQL,这是我正在学习的数据库主题中的一个作业。 我选择的数…

    2025年12月13日 好文分享
    000
  • Python 中 array=[] 和 array=None 的区别是什么?

    Python中的None 在Python中,array=[] 和 array=None 之间存在着区别。 array=[] 创建了一个空的列表,也就是一个不包含任何元素的序列。它是一个 list 类型,其 len() 为 0。你可以使用各种列表方法来操作它,例如追加元素、删除元素和访问元素。 相反,…

    2025年12月13日
    000
  • PyCharm 中如何正确读取文件?

    pycharm 读写文件时路径写法的区别 在 python 中,文件读写操作可以通过 open 函数实现。当使用 pycharm 等 python 开发工具时,在读取文件时路径写法略有不同。 这个问题中遇到的问题是,在 pycharm 中读取文件时显示文件不存在。这是因为路径写法不正确所致。 正确的…

    2025年12月13日
    000
  • Python 中的 `[]` 和 `None` 有什么区别?

    Python中的None 在Python中,数组可以创建为空列表,也可以赋值None。了解这两个操作之间的区别至关重要。 array = [] 创建一个空列表可以使用列表方法操作默认值为空元组() array = None 立即学习“Python免费学习笔记(深入)”; 赋值为NoneType类型不…

    2025年12月13日
    000
  • Python 中 array = [] 和 array = None 的区别是什么?

    Python中的None Python中,array = [] 和 array = None这两种赋值方式有着本质上的区别。 array = [] 这种赋值方式会创建一个空的列表,即array是一个指向空列表的引用。可以使用列表的方法对其进行操作,例如append、insert等。 立即学习“Pyt…

    2025年12月13日
    000
  • Python 中的 None 和 空列表:有什么区别?

    python中的变量类型:none和空列表 在python中,none和空列表是两个截然不同的变量类型,它们在使用和意义上都有很大差异。 空列表 空列表是用中括号定义的,内部没有元素,例如: 立即学习“Python免费学习笔记(深入)”; array = [] 空列表本质上是一个list对象,它具有…

    2025年12月13日
    000
  • Python 中的 None 和 空列表 []:如何选择合适的空值表示?

    python 中特殊值 none 的不同应用 在 python 中,使用 none 表示空值或不存在的值。在以下代码中,我们探讨了 none 与空列表 [] 之间的区别: array1 = []array2 = None array = []:空列表 array1 引用了一个空列表,它不包含任何元素…

    2025年12月13日
    000
  • Python中的多进程编程和多线程编程的区别是什么?

    Python中的多进程编程和多线程编程的区别是什么? 在Python中,多进程编程和多线程编程都是实现并行计算的方法。虽然它们都能同时运行多个任务,但其底层原理和使用方式却有所不同。 多进程编程是利用操作系统的多进程机制来实现并行计算的。在Python中,可以使用multiprocessing模块来…

    2025年12月13日
    000
  • Python中的迭代器和生成器的区别是什么?

    Python中的迭代器和生成器的区别是什么? 在Python编程中,迭代器(iterator)和生成器(generator)都是用于处理可迭代对象的工具。它们两者都可以用于遍历数据,但是在实现上却有一些不同之处。 迭代器是一个对象,它实现了迭代器协议(iterator protocol)。迭代器对象…

    2025年12月13日
    000
  • CodeIgniter 4 应用中的敏感数据保护与认证策略

    本文深入探讨了在codeigniter 4框架中处理敏感客户数据时的安全实践,特别是如何通过会话(session)和自定义过滤器(filters)实现强大的认证机制。我们将详细介绍如何构建一个基于会话的认证守卫,将其应用于受保护的路由,并重点讲解如何利用`configfilters`进行集中化管理,…

    2025年12月13日
    000
  • PHP日期时间计算:解决diff()方法在字符串上调用的致命错误

    本教程旨在解决php中尝试在字符串上调用`datetime`对象的`diff()`方法时遇到的“call to a member function diff() on string”致命错误。文章将深入分析错误原因,并提供详细的解决方案,重点讲解如何正确地使用`datetime`类进行日期时间操作,…

    2025年12月13日
    000
  • PHP Memcache 精准清除与更新特定缓存项指南

    本文详细介绍了如何在php中使用memcache实现特定缓存项的精准清除与更新,避免全量刷新带来的性能损耗。我们将探讨`memcache::delete()`结合`memcache::set()`或`memcache::add()`的最佳实践,并深入解析`memcache::set()`与`memc…

    2025年12月13日
    000

发表回复

登录后才能评论
关注微信