简体   繁体   English

使用 webflux webclient 发出请求时如何正确编码加号 (+)?

[英]How to encode properly the plus sign (+) when making a request with webflux webclient?

I am trying to send an international formatted phone number using spring Webflux Webclient and to read this phone number via another application also using webflux.我正在尝试使用 spring Webflux Webclient 发送国际格式的电话号码,并通过另一个也使用 webflux 的应用程序读取此电话号码。

My code looks like this:我的代码如下所示:

webClient = WebClient.builder()
            .baseUrl(baseUrl)
            .build();

return webClient
            .get()
            .uri(uriBuilder -> uriBuilder
                    .path("/endpoint")
                    .queryParam("phone-number", "+33612345678")
                    .build()
            )
            .retrieve()
            .bodyToMono(String.class);

Unfortunately, somewhere between this call and the receiver, the plus sign is replaced by a space.不幸的是,在这个调用和接收者之间的某个地方,加号被一个空格代替了。 The endpoint receives: " 33612345678" as a String.端点接收:“33612345678”作为字符串。

The.netty debug log of the request shows this:请求的 .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

I tried to encode the phone-number by myself like this:我试图像这样自己编码电话号码:

.queryParam("phone-number", UriUtils.encode("+34612345678", StandardCharsets.UTF_8))

And.netty's log shows: and.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|

It seems that the phone number has been encoded twice.电话号码似乎被编码了两次。

+ -> %2B -> %252B + -> %2B -> %252B

the plus sign has been encoded by UriUtils.encode then uriBuilder has encoded the %.加号已由UriUtils.encode编码,然后 uriBuilder 已编码 %。

The only way I found to make it work is by disabling the encoding of the UriBuilder:我发现让它工作的唯一方法是禁用 UriBuilder 的编码:

 DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
    factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
    this.webClient = WebClient.builder()
            .baseUrl(baseUrl)
            .uriBuilderFactory(factory)
            .build();

and having my custom encoding UriUtils.encode("+34612345678", StandardCharsets.UTF_8)并使用我的自定义编码UriUtils.encode("+34612345678", StandardCharsets.UTF_8)

in which case the.netty's logs looks like expected:在这种情况下 the.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/|

And of course, the endpoint receiving the phone number get: "+33612345678"当然,接收电话号码的端点得到:“+33612345678”

To sum it up, it looks like the UriBuilder is encoding certain sign like "%" but does not encode the "+" sign.总而言之,UriBuilder 似乎正在对某些符号(如“%”)进行编码,但并未对“+”符号进行编码。 Spring reference: https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#web-uri-encoding Spring参考: https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#web-uri-encoding

I am trying to send an international formatted phone number using spring Webflux Webclient and to read this phone number via another application also using webflux.我正在尝试使用 spring Webflux Webclient 发送一个国际格式的电话号码,并通过另一个也使用 webflux 的应用程序读取此电话号码。

My code looks like this :我的代码如下所示:

webClient = WebClient.builder()
            .baseUrl(baseUrl)
            .build();

return webClient
            .get()
            .uri(uriBuilder -> uriBuilder
                    .path("/endpoint")
                    .queryParam("phone-number", "+33612345678")
                    .build()
            )
            .retrieve()
            .bodyToMono(String.class);

Unfortunately, somewhere between this call and the receiver, the plus sign is replaced by a space.不幸的是,在这个调用和接收器之间的某个地方,加号被一个空格代替。 The endpoint receives : " 33612345678" as a String.端点接收:“33612345678”作为字符串。

The netty debug log of the request shows this :请求的 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

I tried to encode the phone-number by myself like this :我试着像这样自己编码电话号码:

.queryParam("phone-number", UriUtils.encode("+34612345678", StandardCharsets.UTF_8))

And netty's log shows : 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|

It seems that the phone number has been encoded twice.电话号码似乎被编码了两次。

+ -> %2B -> %252B + -> %2B -> %252B

the plus sign has been encoded by UriUtils.encode then uriBuilder has encoded the %.加号已由UriUtils.encode编码,然后 uriBuilder 已对 % 进行编码。

The only way I found to make it work is by disabling the encoding of the UriBuilder :我发现让它工作的唯一方法是禁用 UriBuilder 的编码:

 DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
    factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
    this.webClient = WebClient.builder()
            .baseUrl(baseUrl)
            .uriBuilderFactory(factory)
            .build();

and having my custom encoding UriUtils.encode("+34612345678", StandardCharsets.UTF_8)并拥有我的自定义编码UriUtils.encode("+34612345678", StandardCharsets.UTF_8)

in which case the netty's logs looks like expected :在这种情况下,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/|

And of course, the endpoint receiving the phone number get : "+33612345678"当然,接收电话号码的端点会得到:“+33612345678”

To sum it up, it looks like the UriBuilder is encoding certain sign like "%" but does not encode the "+" sign.总而言之,看起来 UriBuilder 正在编码诸如“%”之类的某些符号,但没有对“+”符号进行编码。 Spring reference : https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#web-uri-encoding弹簧参考: https : //docs.spring.io/spring-framework/docs/current/reference/html/web.html#web-uri-encoding

I had the same issue and was able to resolve it in my Kotlin application using:我遇到了同样的问题,并且能够在我的 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>()

A solution provided here , you can try this way 这里提供了一个解决方案,你可以试试这个

DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory();
factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY);
URI uri = factory.uriString("https://spring.io/")
            .queryParam("query", "{query}")
            .build("spring+framework"); 
// http://spring.io/?query=spring%2Bframework

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM