Refine FormHttpMessageConverter exception handling

FormHttpMessageConverter could throw a more specific
HttpMessageNotReadableException instead of an IllegalArgumentException
when the http form data is invalid.

See gh-34594
Signed-off-by: Russell Bolles <rbolles@netflix.com>
This commit is contained in:
Russell Bolles
2025-03-13 12:22:25 -07:00
committed by Sébastien Deleuze
parent 6c231804a0
commit 573e74b8bd
2 changed files with 47 additions and 4 deletions

View File

@@ -49,6 +49,7 @@ import org.springframework.web.testfixture.http.MockHttpOutputMessage;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA;
@@ -132,6 +133,27 @@ class FormHttpMessageConverterTests {
assertThat(result.getFirst("name 3")).as("Invalid result").isNull();
}
@Test
void readInvalidFormWithValueThatWontUrlDecode() {
//java.net.URLDecoder doesn't like negative integer values after a % character
String body = "name+1=value+1&name+2=value+2%" + ((char)-1);
assertInvalidFormIsRejectedWithSpecificException(body);
}
@Test
void readInvalidFormWithNameThatWontUrlDecode() {
//java.net.URLDecoder doesn't like negative integer values after a % character
String body = "name+1=value+1&name+2%" + ((char)-1) + "=value+2";
assertInvalidFormIsRejectedWithSpecificException(body);
}
@Test
void readInvalidFormWithNameWithNoValueThatWontUrlDecode() {
//java.net.URLDecoder doesn't like negative integer values after a % character
String body = "name+1=value+1&name+2%" + ((char)-1);
assertInvalidFormIsRejectedWithSpecificException(body);
}
@Test
void writeForm() throws IOException {
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
@@ -410,6 +432,17 @@ class FormHttpMessageConverterTests {
assertThat(this.converter.canWrite(clazz, mediaType)).as(clazz.getSimpleName() + " : " + mediaType).isFalse();
}
private void assertInvalidFormIsRejectedWithSpecificException(String body) {
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.ISO_8859_1));
inputMessage.getHeaders().setContentType(
new MediaType("application", "x-www-form-urlencoded", StandardCharsets.ISO_8859_1));
assertThatThrownBy(() -> this.converter.read(null, inputMessage))
.isInstanceOf(HttpMessageNotReadableException.class)
.hasCauseInstanceOf(IllegalArgumentException.class)
.hasMessage("Could not decode HTTP form payload");
}
private static class MockHttpOutputMessageRequestContext implements UploadContext {