Support @RequestBody Flux<Part> in WebFlux
This commit turns the Synchronoss NIO Multipart HttpMessageReader into a reader of Flux<Part> and creates a separate reader that aggregates the parts into a MultiValueMap<String, Part>. Issue: SPR-14546
This commit is contained in:
@@ -41,7 +41,8 @@ import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.json.Jackson2JsonDecoder;
|
||||
import org.springframework.http.codec.json.Jackson2JsonEncoder;
|
||||
import org.springframework.http.codec.multipart.SynchronossMultipartHttpMessageReader;
|
||||
import org.springframework.http.codec.multipart.MultipartHttpMessageReader;
|
||||
import org.springframework.http.codec.multipart.SynchronossPartHttpMessageReader;
|
||||
import org.springframework.http.codec.xml.Jaxb2XmlDecoder;
|
||||
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
@@ -63,14 +64,15 @@ public class ServerCodecConfigurerTests {
|
||||
@Test
|
||||
public void defaultReaders() throws Exception {
|
||||
List<HttpMessageReader<?>> readers = this.configurer.getReaders();
|
||||
assertEquals(10, readers.size());
|
||||
assertEquals(11, readers.size());
|
||||
assertEquals(ByteArrayDecoder.class, getNextDecoder(readers).getClass());
|
||||
assertEquals(ByteBufferDecoder.class, getNextDecoder(readers).getClass());
|
||||
assertEquals(DataBufferDecoder.class, getNextDecoder(readers).getClass());
|
||||
assertEquals(ResourceDecoder.class, getNextDecoder(readers).getClass());
|
||||
assertStringDecoder(getNextDecoder(readers), true);
|
||||
assertEquals(FormHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass());
|
||||
assertEquals(SynchronossMultipartHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass());
|
||||
assertEquals(SynchronossPartHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass());
|
||||
assertEquals(MultipartHttpMessageReader.class, readers.get(this.index.getAndIncrement()).getClass());
|
||||
assertEquals(Jaxb2XmlDecoder.class, getNextDecoder(readers).getClass());
|
||||
assertEquals(Jackson2JsonDecoder.class, getNextDecoder(readers).getClass());
|
||||
assertStringDecoder(getNextDecoder(readers), false);
|
||||
|
||||
@@ -102,7 +102,9 @@ public class MultipartHttpMessageWriterTests {
|
||||
assertNotNull("No boundary found", contentType.getParameter("boundary"));
|
||||
|
||||
// see if Synchronoss NIO Multipart can read what we wrote
|
||||
SynchronossMultipartHttpMessageReader reader = new SynchronossMultipartHttpMessageReader();
|
||||
SynchronossPartHttpMessageReader synchronossReader = new SynchronossPartHttpMessageReader();
|
||||
MultipartHttpMessageReader reader = new MultipartHttpMessageReader(synchronossReader);
|
||||
|
||||
MockServerHttpRequest request = MockServerHttpRequest.post("/foo")
|
||||
.header(HttpHeaders.CONTENT_TYPE, contentType.toString())
|
||||
.body(response.getBody());
|
||||
|
||||
@@ -32,53 +32,57 @@ import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.MockHttpOutputMessage;
|
||||
import org.springframework.http.codec.HttpMessageReader;
|
||||
import org.springframework.http.converter.FormHttpMessageConverter;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import static java.util.Collections.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.http.HttpHeaders.*;
|
||||
import static org.springframework.http.MediaType.*;
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.core.ResolvableType.forClassWithGenerics;
|
||||
import static org.springframework.http.HttpHeaders.CONTENT_LENGTH;
|
||||
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
|
||||
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA;
|
||||
|
||||
/**
|
||||
* @author Sebastien Deleuze
|
||||
*/
|
||||
public class SynchronossMultipartHttpMessageReaderTests {
|
||||
public class SynchronossPartHttpMessageReaderTests {
|
||||
|
||||
private final HttpMessageReader<MultiValueMap<String, Part>> reader = new SynchronossMultipartHttpMessageReader();
|
||||
private final MultipartHttpMessageReader reader =
|
||||
new MultipartHttpMessageReader(new SynchronossPartHttpMessageReader());
|
||||
|
||||
|
||||
@Test
|
||||
public void canRead() {
|
||||
assertTrue(this.reader.canRead(
|
||||
ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, Part.class),
|
||||
forClassWithGenerics(MultiValueMap.class, String.class, Part.class),
|
||||
MediaType.MULTIPART_FORM_DATA));
|
||||
|
||||
assertFalse(this.reader.canRead(
|
||||
ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, Object.class),
|
||||
forClassWithGenerics(MultiValueMap.class, String.class, Object.class),
|
||||
MediaType.MULTIPART_FORM_DATA));
|
||||
|
||||
assertFalse(this.reader.canRead(
|
||||
ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, String.class),
|
||||
forClassWithGenerics(MultiValueMap.class, String.class, String.class),
|
||||
MediaType.MULTIPART_FORM_DATA));
|
||||
|
||||
assertFalse(this.reader.canRead(
|
||||
ResolvableType.forClassWithGenerics(Map.class, String.class, String.class),
|
||||
forClassWithGenerics(Map.class, String.class, String.class),
|
||||
MediaType.MULTIPART_FORM_DATA));
|
||||
|
||||
assertFalse(this.reader.canRead(
|
||||
ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, Part.class),
|
||||
forClassWithGenerics(MultiValueMap.class, String.class, Part.class),
|
||||
MediaType.APPLICATION_FORM_URLENCODED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveParts() throws IOException {
|
||||
ServerHttpRequest request = generateMultipartRequest();
|
||||
ResolvableType elementType = ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, Part.class);
|
||||
ResolvableType elementType = forClassWithGenerics(MultiValueMap.class, String.class, Part.class);
|
||||
MultiValueMap<String, Part> parts = this.reader.readMono(elementType, request, emptyMap()).block();
|
||||
assertEquals(2, parts.size());
|
||||
|
||||
@@ -105,7 +109,7 @@ public class SynchronossMultipartHttpMessageReaderTests {
|
||||
@Test
|
||||
public void bodyError() {
|
||||
ServerHttpRequest request = generateErrorMultipartRequest();
|
||||
ResolvableType elementType = ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, Part.class);
|
||||
ResolvableType elementType = forClassWithGenerics(MultiValueMap.class, String.class, Part.class);
|
||||
StepVerifier.create(this.reader.readMono(elementType, request, emptyMap())).verifyError();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user