Add multipart support to WebFlux functional API

Issue: SPR-14546
This commit is contained in:
Sebastien Deleuze
2017-04-27 19:04:41 +02:00
parent 852dc84d38
commit a712c19661
10 changed files with 187 additions and 5 deletions

View File

@@ -103,7 +103,7 @@ public class DelegatingWebFluxConfigurationTests {
verify(webFluxConfigurer).configureArgumentResolvers(any());
assertSame(formatterRegistry.getValue(), initializerConversionService);
assertEquals(9, codecsConfigurer.getValue().getReaders().size());
assertEquals(10, codecsConfigurer.getValue().getReaders().size());
}
@Test

View File

@@ -127,7 +127,7 @@ public class WebFluxConfigurationSupportTests {
assertNotNull(adapter);
List<HttpMessageReader<?>> readers = adapter.getMessageCodecConfigurer().getReaders();
assertEquals(9, readers.size());
assertEquals(10, readers.size());
assertHasMessageReader(readers, forClass(byte[].class), APPLICATION_OCTET_STREAM);
assertHasMessageReader(readers, forClass(ByteBuffer.class), APPLICATION_OCTET_STREAM);

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.reactive.function;
import java.util.Map;
import org.junit.Test;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.multipart.Part;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.server.AbstractRouterFunctionIntegrationTests;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import static org.junit.Assert.assertEquals;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
public class MultipartIntegrationTests extends AbstractRouterFunctionIntegrationTests {
private final WebClient webClient = WebClient.create();
@Test
public void multipart() {
Mono<ClientResponse> result = webClient
.post()
.uri("http://localhost:" + this.port + "/")
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(BodyInserters.fromMultipartData(generateBody()))
.exchange();
StepVerifier
.create(result)
.consumeNextWith(response -> {
assertEquals(HttpStatus.OK, response.statusCode());
})
.verifyComplete();
}
private MultiValueMap<String, Object> generateBody() {
HttpHeaders fooHeaders = new HttpHeaders();
fooHeaders.setContentType(MediaType.TEXT_PLAIN);
ClassPathResource fooResource = new ClassPathResource("org/springframework/http/codec/multipart/foo.txt");
HttpEntity<ClassPathResource> fooPart = new HttpEntity<>(fooResource, fooHeaders);
HttpEntity<String> barPart = new HttpEntity<>("bar");
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
parts.add("fooPart", fooPart);
parts.add("barPart", barPart);
return parts;
}
@Override
protected RouterFunction<ServerResponse> routerFunction() {
MultipartHandler multipartHandler = new MultipartHandler();
return route(POST("/"), multipartHandler::handle);
}
private static class MultipartHandler {
public Mono<ServerResponse> handle(ServerRequest request) {
return request
.body(BodyExtractors.toMultipartData())
.flatMap(map -> {
Map<String, Part> parts = map.toSingleValueMap();
try {
assertEquals(2, parts.size());
assertEquals("foo.txt", parts.get("fooPart").getFilename().get());
assertEquals("bar", parts.get("barPart").getContentAsString().block());
}
catch(Exception e) {
return Mono.error(e);
}
return ServerResponse.ok().build();
});
}
}
}