【问题标题】:How to encode properly the plus sign (+) when making a request with webflux webclient?使用 webflux webclient 发出请求时如何正确编码加号 (+)?
【发布时间】: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 进行编码,它在 queryparam docs.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


【解决方案1】:

我遇到了同样的问题,但从Spring reference you linked 找到了解决方法。

这应该适合你:

return webClient
            .get()
            .uri(uriBuilder -> UriComponentsBuilder.fromUri(uriBuilder.build())
                    .path("/endpoint")
                    .queryParam("phone-number", "{phone-number}")
                    .encode()
                    .buildAndExpand("+33612345678")
                    .toUri()
            )
            .retrieve()
            .bodyToMono(String.class);

【讨论】:

  • 感谢您的回答。不幸的是,我无法测试它,因为我们从项目中完全删除了 spring webflux!我会把它标记为正确的答案,直到有人证明我错了:)
【解决方案2】:

我遇到了同样的问题,并且能够在我的 Kotlin 应用程序中使用:

webClient.get()
    .uri { uriBuilder ->
        val queryParams = mapOf(
            "phone-number" to "+33612345678",
            "mobile-number" to "+61432111222"
        )
        uriBuilder.path("/endpoint")
            .apply { 
                queryParams.keys.forEach { key ->
                    queryParam(key, "{$key}")
                }
            }
            .build(queryParams)
    }
    .retrieve()
    .bodyToMono<String>()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-30
    • 1970-01-01
    • 2022-01-25
    • 2020-04-14
    • 2020-07-12
    • 2016-08-11
    • 2020-09-02
    • 2019-10-12
    相关资源
    最近更新 更多