正确解析包含“+”字符的字段

2024-05-03

我遇到了一个奇怪的情况,我在其中重现了https://github.com/lgueye/uri-parameters-behavior https://github.com/lgueye/uri-parameters-behavior

自从我们迁移到弹簧启动 2 (弹簧框架5)当请求我们的后端之一时GET方法中我们遇到了以下情况:所有带有 a 的字段+char 被更改为(空白)到达后端时的字符

以下值已更改:

  • +412386789(电话号码)输入** 412386789**
  • 2019-03-22T17:18:39.621+02:00(java8 ZonedDateTime)进入2019-03-22T17:18:39.621 02:00(导致org.springframework.validation.BindException

我在 stackoverflow 上花了相当长的时间(https://github.com/spring-projects/spring-framework/issues/14464#issuecomment-453397378 https://github.com/spring-projects/spring-framework/issues/14464#issuecomment-453397378)和github(https://github.com/spring-projects/spring-framework/issues/21577 https://github.com/spring-projects/spring-framework/issues/21577)

我已经实现了 mockMvc 单元测试和集成测试

单元测试表现正常 集成测试失败(就像我们的生产)

谁能帮我解决这个问题吗?我的目标显然是让集成测试通过。

感谢您的帮助。

Louis


整个错位来自于以下事实:存在如何将空间编码/解码为非标准实践"+".

可以说空间可以(正在)被编码成"+" or "%20".

例如,Google 对搜索字符串执行此操作:

https://www.google.com/search?q=test+my+space+delimited+entry

rfc1866, section-8.2.2 https://www.rfc-editor.org/rfc/rfc1866#section-8.2.2指出 GET 请求的查询部分应编码为'application/x-www-form-urlencoded'.

所有表单的默认编码是`application/x-www-form-
urlencoded'。表单数据集在此媒体类型中表示为
如下:

  1. 表单字段名称和值被转义:space 字符被替换为“+”.

另一方面rfc3986 https://www.rfc-editor.org/rfc/rfc3986规定 URL 中的空格必须使用编码"%20".

这基本上意味着有不同的标准来编码空格,具体取决于它们在 URI 中的位置语法成分 https://www.rfc-editor.org/rfc/rfc3986#page-16.

     foo://example.com:8042/over/there?name=ferret#nose
     \_/   \______________/\_________/ \_________/ \__/
      |           |            |            |        |
   scheme     authority       path        query   fragment
      |   _____________________|__
     / \ /                        \
     urn:example:animal:ferret:nose

基于这些评论,我们可以在 URI 中的 GET http 调用中声明:

  • 之前有空格"?"需要编码为"%20"
  • 之后的空格"?"查询参数中需要编码为"+"
  • 意思是"+"符号需要编码为"%2B"在查询参数中

Spring实现遵循rfc规范,所以这就是为什么当你发送“+412386789”在查询参数中,"+"符号被解释为空白字符,它到达后端为“412386789”.

看着:

final URI uri = UriComponentsBuilder.fromHttpUrl("http://localhost")
                                    .port(port)
                                    .path("/events")
                                    .queryParams(params)
                                    .build()
                                    .toUri();

你会发现:

"foo#bar@quizz+foo-bazz//quir."被编码为"foo%23bar@quizz+foo-bazz//quir."符合规范(rfc3986 https://www.rfc-editor.org/rfc/rfc3986).

所以如果你想要"+"查询参数中的 char 不被解释为空格,您需要将其编码为"%2B".

您发送到后端的参数应如下所示:

   params.add("id", id);
   params.add("device", device);
   params.add("phoneNumber", "%2B225697845");
   params.add("timestamp", "2019-03-25T15%3A09%3A44.703088%2B02%3A00");
   params.add("value", "foo%23bar%40quizz%2Bfoo-bazz%2F%2Fquir.");

为了做到这一点,你可以使用UrlEncoder https://docs.oracle.com/javase/8/docs/api/index.html?java/net/URLEncoder.html将参数传递给地图时。当心 UriComponentsBuilder 对你的东西进行双重编码!

您可以通过以下方式获得正确的 URL:

final MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("id", id);
params.add("device", device);
String uft8Charset = StandardCharsets.UTF_8.toString();
params.add("phoneNumber", URLEncoder.encode(phoneNumber, uft8Charset));
params.add("timestamp", URLEncoder.encode(timestamp.toString(), uft8Charset));
params.add("value", URLEncoder.encode(value, uft8Charset));

final URI uri = UriComponentsBuilder.fromHttpUrl("http://localhost")
                                    .port(port)
                                    .path("/events")
                                    .queryParams(params)
                                    .build(true)
                                    .toUri();

请注意,将“true”传递给build()方法关闭编码,因此这意味着 URI 部分中的方案、主机等将无法正确编码UriComponentsBuilder https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/UriComponentsBuilder.html.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

正确解析包含“+”字符的字段 的相关文章

随机推荐

  • Android Http url 连接在 getInputstream 抛出文件未找到异常

    我正在尝试将一些 json 字符串发布到休息服务器 但在获取输入流时遇到 java 文件未找到异常 这是我的代码 package com muzima view sample activities import javax servlet
  • 如何阻止 HTML 输入字段中的特殊字符? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我只是想问一下如何在html输入字段中阻止 等特殊字符 为什么不使用html5呢
  • 使用字符串函数查找周期字符串

    我正在寻找一种方法来检查字符串是否是周期性的或不使用 JavaScript 要匹配的示例字符串可以是11223331122333 然而 10101不应该匹配 来自 python 我使用了 RegEx 1 但速度相当慢 有没有任何字符串方法可
  • 如何使用 Android 加速计?

    我正在尝试构建一个应用程序来读取手机上加速度计的值 该应用程序仅支持 Android 2 1 如何使用 2 1 兼容代码读取加速度计 从这个开始 public class yourActivity extends Activity impl
  • 正则表达式或多个/单个字符

    我正在动态地制作一个正则表达式 我希望它匹配以下内容 lem le m levm lecm 基本上是 lem 但在 m 之前它可以有任意数量 或任何字符中的任何一个 现在我有 le 0 m 你可以在以下位置看到它http regexr co
  • 谷歌分析实时不工作

    我正在使用这段代码来使用Google Analytics为了获取实时信息和应用程序评论 代码位于 AppDelegate 中 GAI sharedInstance trackUncaughtExceptions YES GAI shared
  • 如何使用Android读取Service中的加速度计数据

    通常 在 Android 中 我们通过重写 OnSensorChanged 函数来读取 Activity 中的加速度计数据 我很好奇我们如何在 服务 中做到这一点 谢谢 文森特 实际上OnSensorChanged SensorEvent
  • 查找使用连接的位置 Excel VBA

    我有大量需要优化的 Excel 2013 工作簿 每个工作簿都有多个工作表和多个数据连接 我正在寻找一种快速列出的方法 连接名称 连接字符串 使用连接的位置 工作表名称或范围很有用 我可以在连接对话框中看到所有这些信息 但无法以编程方式跟踪
  • 从 SQL Server 中的字符串中提取子字符串

    我需要从字符串中提取子字符串的一部分 如下所示 YY 12 Yellow ABC WSA Thisone A SS 4MON DHHE A A 我需要按如下方式提取字符串 Yellow Thisone DHHE 你可以使用这样的东西 dec
  • 未找到“Guzzle\Http\Client”类

    我正在尝试在 sitepoint 上跟进本教程http www sitepoint com guzzle php http client http www sitepoint com guzzle php http client 我这里是一
  • 如何取消 boost asio io_service 帖子

    如何取消已发布的回调 getIoService gt post boost bind MyClass myCallback this 并保持其他发布的回调不变 问题是我有一些对象从不同线程接收事件 并将它们发布到 ioservice 以便处
  • 当 SwingWorker 在后台工作时,对话框没有响应

    基本上我得到了一个以 main 方法作为入口点的 JFrame 在这个主要方法中 程序必须下载一些图像 为了通知用户程序将随时启动 我想显示一个简单的对话框 如果我将对话框设置为模式 我必须在启动程序后关闭它才能触发下载 如果我将其设置为非
  • 如何判断当前运行的 Apple Watch 尺寸/尺寸是 38 毫米还是 42 毫米?

    我们知道Apple Watch有两种屏幕尺寸 38mm和42mm 这WKInterfaceDevice类提供了一个名为的可读属性screenBounds 我写了一个扩展WKInterfaceDevice 尝试添加一种方法来检测当前设备类型
  • 观察 CALayer 中的动画属性变化

    我有一个CABasicAnimation动画 a 的属性CALayer e g bounds origin 我希望能够观察属性随时间的变化 但还没有真正找到一种 100 有效的方法 我尝试使用 KVO 键值观察 presentationLa
  • 如何为 SSMS 2019 (v18) 创建扩展

    SQL Server Management Studio 18 RC1 https learn microsoft com en us sql ssms download sql server management studio ssms
  • 如何自动创建 WPF Viewmodel 属性

    我在 WPF 项目中使用 Visual Studio 17 和 Resharper 该项目向用户显示大量信息 因此我有很多如下所示的属性 private double foo public double Foo get return foo
  • 从 Restful 身份验证迁移到 Devise

    许多 Rails 2 3 应用程序正在使用 Restful Authentication 但该插件似乎与 Rails 3 存在一些问题 在升级到 Rails 3 时 我一直在使用 Devise 有什么办法可以顺利地从 Restful Aut
  • 明确的控制不会处置它们——风险是什么?

    有多个线程 a https stackoverflow com questions 1757116 remove tabpage dispose or clear or both b https stackoverflow com ques
  • 如何使用 JavaScript 或 jQuery 从 URL 下载文件?

    我使用 jQuery fileDownload 插件从 URL 下载文件 fileDownload url contentType text csv contentDisposition attachment filename url sp
  • 正确解析包含“+”字符的字段

    我遇到了一个奇怪的情况 我在其中重现了https github com lgueye uri parameters behavior https github com lgueye uri parameters behavior 自从我们迁