1

We are using Spring Cloud Gateway (MVC version) in front o a Rails service (let's call it mailbox) and are struggling when the value of a query parameter includes the + (plus) character. Here is an example:

  1. Client sends a request to the gateway with [email protected]
  2. Gateway decodes the parameter value, turning + into a space.
  3. Before sending the request to mailbox, it encodes back the value, resulting in email=bob%[email protected]
  4. When receiving this param, mailbox decodes it as email=bob [email protected] which makes it fail

An alternative was to encode + in the client, but then we have:

  1. Client sends a request to the gateway with ?email=bob%[email protected]
  2. Gateway decodes the parameter value, turning %2B into +.
  3. Before sending the request to mailbox, it encodes back the value but, given that + is not considered special character, it stays as [email protected]
  4. When receiving this param, mailbox decodes it as email=bob [email protected] which makes it fail

I can't find a way to either tell gateway not to decode the original request or force it to encode + before sending the request to mailbox. Is there any way to do that? Is there any other solution? I can't think of anything. It's like all the steps taken are okay (first decode, then encode), but the final result is wrong. I need mailbox to receive an email with a + in it, but I can't.

Thanks for your help!

1 Answer 1

2

We encountered the same issue and were able to work around the problem by manually encoding + in the forwarded requests after the existing encoder has run.

This was achieved by using a customised ClientHttpRequestFactory as follows:

@Configuration
class WebMvcConfiguration {

    @Bean
    fun clientHttpRequestFactory(): ClientHttpRequestFactory =
        CustomClientHttpRequestFactory()

}
class CustomClientHttpRequestFactory : JdkClientHttpRequestFactory() {

    override fun createRequest(uri: URI, httpMethod: HttpMethod): ClientHttpRequest {
        val encodedURI = URI(customUriEncode(uri.toString()))
        return super.createRequest(encodedURI, httpMethod)
    }

    private fun customUriEncode(str: String): String = 
        str.replace(oldValue = "+", newValue = "%2B")

}

We believe this to be safe, because both + and %20 in the original request are decoded into (a space) before it reaches the request factory, so will not be re-encoded back into %2B.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.