From aed94c2cc8f56b0ed2644c364e240abcab17981b Mon Sep 17 00:00:00 2001 From: config25 Date: Tue, 31 Mar 2026 10:23:23 +0900 Subject: [PATCH 1/2] Fix URL decoding charset mismatch in MockMvcRequestConverter MockMvcRequestConverter.decode() was using StandardCharsets.US_ASCII for URL decoding while urlEncode() in the same class uses StandardCharsets.UTF_8. This mismatch causes non-ASCII characters in query parameters to be corrupted. Align with QueryParameters.decode() which correctly uses UTF_8. Fixes gh-1033 Signed-off-by: config25 --- .../mockmvc/MockMvcRequestConverter.java | 2 +- .../mockmvc/MockMvcRequestConverterTests.java | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverter.java b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverter.java index e8ddd1e8..0fe60b79 100644 --- a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverter.java +++ b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverter.java @@ -284,7 +284,7 @@ private static void processParameter(String parameter, MultiValueMap Date: Wed, 1 Apr 2026 08:28:05 +0900 Subject: [PATCH 2/2] Replace non-ASCII tests with one that exercises decode() Signed-off-by: config25 --- .../mockmvc/MockMvcRequestConverterTests.java | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverterTests.java b/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverterTests.java index a30cd780..7b384c0e 100644 --- a/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverterTests.java +++ b/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverterTests.java @@ -150,23 +150,6 @@ void postRequestWithParametersCreatesFormUrlEncodedContent() { assertThat(request.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_FORM_URLENCODED); } - @Test - void getRequestWithNonAsciiParametersProducesCorrectQueryString() { - OperationRequest request = createOperationRequest( - MockMvcRequestBuilders.get("/foo").param("name", "\uD64D\uAE38\uB3D9")); - assertThat(request.getUri()) - .isEqualTo(URI.create("http://localhost/foo?name=%ED%99%8D%EA%B8%B8%EB%8F%99")); - assertThat(request.getMethod()).isEqualTo(HttpMethod.GET); - } - - @Test - void postRequestWithNonAsciiParametersCreatesCorrectFormUrlEncodedContent() { - OperationRequest request = createOperationRequest( - MockMvcRequestBuilders.post("/foo").param("name", "\uD64D\uAE38\uB3D9")); - assertThat(request.getContentAsString()).isEqualTo("name=%ED%99%8D%EA%B8%B8%EB%8F%99"); - assertThat(request.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_FORM_URLENCODED); - } - @Test void postRequestWithParametersAndQueryStringCreatesFormUrlEncodedContentWithoutDuplication() { OperationRequest request = createOperationRequest( @@ -177,6 +160,19 @@ void postRequestWithParametersAndQueryStringCreatesFormUrlEncodedContentWithoutD assertThat(request.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_FORM_URLENCODED); } + @Test + void postRequestWithNonAsciiParametersAndQueryStringCreatesFormUrlEncodedContentWithoutDuplication() { + OperationRequest request = createOperationRequest(MockMvcRequestBuilders + .post("/foo?name=%ED%99%8D%EA%B8%B8%EB%8F%99") + .param("name", "\uD64D\uAE38\uB3D9") + .param("other", "\uD64D\uAE38\uB3D9")); + assertThat(request.getUri()) + .isEqualTo(URI.create("http://localhost/foo?name=%ED%99%8D%EA%B8%B8%EB%8F%99")); + assertThat(request.getMethod()).isEqualTo(HttpMethod.POST); + assertThat(request.getContentAsString()).isEqualTo("other=%ED%99%8D%EA%B8%B8%EB%8F%99"); + assertThat(request.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_FORM_URLENCODED); + } + @Test void mockMultipartFileUpload() { OperationRequest request = createOperationRequest(MockMvcRequestBuilders.multipart("/foo")