【发布时间】:2021-02-24 13:27:39
【问题描述】:
我正在尝试使用 spring Webflux Webclient 发送一个国际格式的电话号码,并通过另一个同样使用 webflux 的应用程序读取这个电话号码。
我的代码如下所示:
webClient = WebClient.builder()
.baseUrl(baseUrl)
.build();
return webClient
.get()
.uri(uriBuilder -> uriBuilder
.path("/endpoint")
.queryParam("phone-number", "+33612345678")
.build()
)
.retrieve()
.bodyToMono(String.class);
不幸的是,在这个调用和接收者之间的某个地方,加号被一个空格替换了。 端点接收:“33612345678”作为字符串。
请求的 netty 调试日志显示:
+--------+-------------------------------------------------+----------------+
|00000000| 47 45 54 20 2f 63 75 73 74 6f 6d 65 72 73 3f 70 |GET /endpoint?p|
|00000010| 68 6f 6e 65 2d 6e 75 6d 62 65 72 3d 2b 33 33 36 |hone-number=+336|
|00000020| 31 32 33 34 35 36 37 38 26 6f 6e 6c 79 2d 72 65 |12345678
我尝试像这样自己对电话号码进行编码:
.queryParam("phone-number", UriUtils.encode("+34612345678", StandardCharsets.UTF_8))
而netty的日志显示:
+--------+-------------------------------------------------+----------------+
|00000000| 47 45 54 20 2f 63 75 73 74 6f 6d 65 72 73 3f 70 |GET /endpoint?p|
|00000010| 68 6f 6e 65 2d 6e 75 6d 62 65 72 3d 25 32 35 32 |hone-number=%252|
|00000020| 42 33 34 36 31 32 33 34 35 36 37 38 20 48 54 54 |B34612345678 HTT|
电话号码好像被编码了两次。
+ -> %2B -> %252B
加号已由UriUtils.encode 编码,然后uriBuilder 已编码%。
我发现让它工作的唯一方法是禁用 UriBuilder 的编码:
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
this.webClient = WebClient.builder()
.baseUrl(baseUrl)
.uriBuilderFactory(factory)
.build();
还有我的自定义编码UriUtils.encode("+34612345678", StandardCharsets.UTF_8)
在这种情况下,netty 的日志看起来像预期的那样:
+--------+-------------------------------------------------+----------------+
|00000000| 47 45 54 20 2f 63 75 73 74 6f 6d 65 72 73 3f 70 |GET /endpoint?p|
|00000010| 68 6f 6e 65 2d 6e 75 6d 62 65 72 3d 25 32 42 33 |hone-number=%2B3|
|00000020| 34 36 31 32 33 34 35 36 37 38 20 48 54 54 50 2f |4612345678 HTTP/|
当然,接收电话号码的端点会得到:“+33612345678”
总而言之,看起来 UriBuilder 正在对某些符号进行编码,例如“%”,但没有对“+”符号进行编码。 弹簧参考:https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#web-uri-encoding
【问题讨论】:
-
这是正确的,加号未按照 RFC 3986 进行编码,它在
queryparamdocs.spring.io/spring-framework/docs/current/javadoc-api/org/… 的春季文档中提到您可以使用模板 docs.spring.io/spring-framework/docs/current/reference/html/… 强制执行更严格的编码 -
感谢您将我指向
queryparam文档。我试图强制执行更严格的编码,但我不明白。它说TEMPLATE_AND_VALUES:使用UriComponentsBuilder#encode(),UriComponentsBuilder#encode(): Pre-encodes首先使用URI模板,然后在扩展时严格编码URI变量。用“;”给出一个例子字符:第一个选项替换“;”在 URI 变量中带有“%3B”。这就是我通过强制factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.TEMPLATE_AND_VALUES);所做的,但它不编码“;”也不是“+” -
尝试使用
VALUES_ONLY编码 -
我都试过了,但没有一个能编码;或 + 号 :(
标签: java spring spring-webflux