Last active
November 21, 2024 14:28
-
-
Save boly38/94fddf8ec9acda887cfa6f1b5b07ae7e to your computer and use it in GitHub Desktop.
Stackoverflow question related Test https://stackoverflow.com/questions/54294843/plus-sign-not-encoded-with-resttemplate-using-string-url-but-interpreted
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.company.interceptors; | |
import java.io.IOException; | |
import java.net.URI; | |
import lombok.NonNull; | |
import lombok.extern.slf4j.Slf4j; | |
import org.springframework.http.HttpRequest; | |
import org.springframework.http.client.ClientHttpRequestExecution; | |
import org.springframework.http.client.ClientHttpRequestInterceptor; | |
import org.springframework.http.client.ClientHttpResponse; | |
import org.springframework.http.client.support.HttpRequestWrapper; | |
import org.springframework.util.StringUtils; | |
import org.springframework.web.util.UriComponentsBuilder; | |
/** | |
* RestTemplate, the '+' sign is not encoded to '%2B' anymore (changes by SPR-14828). | |
* <a href="https://stackoverflow.com/questions/54294843/plus-sign-not-encoded-with-resttemplate-using-string-url-but-interpreted">SO + interpreted as space</a> | |
* RFC3986 doesn't list '+' as a reserved character, | |
* but it is still interpreted as a ' ' (space) when received in a Spring Boot endpoint | |
*/ | |
@Slf4j | |
public class PlusEncoderInterceptor implements ClientHttpRequestInterceptor { | |
@Override | |
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { | |
return execution.execute(new HttpRequestWrapper(request) { | |
@Override | |
public @NonNull URI getURI() { | |
URI u = super.getURI(); | |
String rawQuery = u.getRawQuery(); | |
String strictlyEscapedQuery = StringUtils | |
.replace(rawQuery, "+", "%2B"); | |
if (log.isDebugEnabled() && !strictlyEscapedQuery.equals(rawQuery)) { | |
log.debug("Plus intercept> {} => {}", rawQuery, strictlyEscapedQuery); | |
} | |
return UriComponentsBuilder.fromUri(u) | |
.replaceQuery(strictlyEscapedQuery) | |
.build(true).toUri(); | |
} | |
}, body); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import static org.junit.jupiter.api.Assertions.*; | |
import static org.mockito.ArgumentMatchers.any; | |
import static org.mockito.Mockito.mock; | |
import static org.mockito.Mockito.verify; | |
import static org.mockito.Mockito.when; | |
import java.net.URI; | |
import org.junit.jupiter.api.BeforeEach; | |
import org.junit.jupiter.api.Test; | |
import org.mockito.ArgumentCaptor; | |
import org.springframework.http.HttpRequest; | |
import org.springframework.http.client.ClientHttpRequestExecution; | |
import org.springframework.http.client.ClientHttpResponse; | |
class PlusEncoderInterceptorTest { | |
private PlusEncoderInterceptor interceptor; | |
private HttpRequest request; | |
private ClientHttpRequestExecution execution; | |
@BeforeEach | |
public void setUp() { | |
interceptor = new PlusEncoderInterceptor(); | |
request = mock(HttpRequest.class); | |
execution = mock(ClientHttpRequestExecution.class); | |
} | |
@Test | |
void testPlusCharacterEncoding() throws Exception { | |
String originalQuery = "param1=value1+value2"; | |
URI originalUri = URI.create("http://example.com/api?" + originalQuery); | |
when(request.getURI()).thenReturn(originalUri); | |
ClientHttpResponse response = mock(ClientHttpResponse.class); | |
when(execution.execute(any(), any())).thenReturn(response); | |
// WHEN | |
interceptor.intercept(request, new byte[0], execution); | |
ArgumentCaptor<HttpRequest> requestCaptor = ArgumentCaptor.forClass(HttpRequest.class); | |
verify(execution).execute(requestCaptor.capture(), any()); | |
URI capturedUri = requestCaptor.getValue().getURI(); | |
String capturedQuery = capturedUri.getRawQuery(); | |
// check '+' has been replaced by '%2B' | |
assertEquals("param1=value1%2Bvalue2", capturedQuery); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment