Added form support to Body[Inserter|Extractor]

- Added BodyInserter for MultiValueMap form data in BodyInserters
 - Added BodyExtractor to MultiValueMap in BodyExtractors

Issue: SPR-15144
This commit is contained in:
Arjen Poutsma
2017-01-18 15:35:55 +01:00
parent bc87c27b18
commit 13a7563ddd
4 changed files with 152 additions and 25 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -41,11 +41,14 @@ import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ReactiveHttpInputMessage;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.FormHttpMessageReader;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.UnsupportedMediaTypeException;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.xml.Jaxb2XmlDecoder;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.util.MultiValueMap;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -68,6 +71,7 @@ public class BodyExtractorsTests {
messageReaders.add(new DecoderHttpMessageReader<>(new StringDecoder()));
messageReaders.add(new DecoderHttpMessageReader<>(new Jaxb2XmlDecoder()));
messageReaders.add(new DecoderHttpMessageReader<>(new Jackson2JsonDecoder()));
messageReaders.add(new FormHttpMessageReader());
this.context = new BodyExtractor.Context() {
@Override
@@ -79,7 +83,7 @@ public class BodyExtractorsTests {
return hints;
}
};
this.hints = new HashMap();
this.hints = new HashMap<String, Object>();
}
@Test
@@ -202,6 +206,36 @@ public class BodyExtractorsTests {
.verify();
}
@Test
public void toFormData() throws Exception {
BodyExtractor<Mono<MultiValueMap<String, String>>, ServerHttpRequest> extractor = BodyExtractors.toFormData();
DefaultDataBufferFactory factory = new DefaultDataBufferFactory();
DefaultDataBuffer dataBuffer =
factory.wrap(ByteBuffer.wrap("name+1=value+1&name+2=value+2%2B1&name+2=value+2%2B2&name+3".getBytes(StandardCharsets.UTF_8)));
Flux<DataBuffer> body = Flux.just(dataBuffer);
MockServerHttpRequest request = MockServerHttpRequest.post("/")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(body);
Mono<MultiValueMap<String, String>> result = extractor.extract(request, this.context);
StepVerifier.create(result)
.consumeNextWith(form -> {
assertEquals("Invalid result", 3, form.size());
assertEquals("Invalid result", "value 1", form.getFirst("name 1"));
List<String> values = form.get("name 2");
assertEquals("Invalid result", 2, values.size());
assertEquals("Invalid result", "value 2+1", values.get(0));
assertEquals("Invalid result", "value 2+2", values.get(1));
assertNull("Invalid result", form.getFirst("name 3"));
})
.expectComplete()
.verify();
}
@Test
public void toDataBuffers() throws Exception {
BodyExtractor<Flux<DataBuffer>, ReactiveHttpInputMessage> extractor = BodyExtractors.toDataBuffers();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -16,6 +16,7 @@
package org.springframework.web.reactive.function;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
@@ -41,8 +42,11 @@ import org.springframework.core.io.Resource;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DefaultDataBuffer;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.ReactiveHttpOutputMessage;
import org.springframework.http.client.reactive.ClientHttpRequest;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.FormHttpMessageWriter;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.ServerSentEvent;
@@ -50,7 +54,10 @@ import org.springframework.http.codec.ServerSentEventHttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.mock.http.client.reactive.test.MockClientHttpRequest;
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertArrayEquals;
@@ -77,6 +84,7 @@ public class BodyInsertersTests {
messageWriters.add(new EncoderHttpMessageWriter<>(jsonEncoder));
messageWriters
.add(new ServerSentEventHttpMessageWriter(Collections.singletonList(jsonEncoder)));
messageWriters.add(new FormHttpMessageWriter());
this.context = new BodyInserter.Context() {
@Override
@@ -198,6 +206,33 @@ public class BodyInsertersTests {
StepVerifier.create(result).expectNextCount(0).expectComplete().verify();
}
@Test
public void ofFormData() throws Exception {
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.set("name 1", "value 1");
body.add("name 2", "value 2+1");
body.add("name 2", "value 2+2");
body.add("name 3", null);
BodyInserter<MultiValueMap<String, String>, ClientHttpRequest>
inserter = BodyInserters.fromFormData(body);
MockClientHttpRequest request = new MockClientHttpRequest(HttpMethod.GET, URI.create("http://example.com"));
Mono<Void> result = inserter.insert(request, this.context);
StepVerifier.create(result).expectComplete().verify();
StepVerifier.create(request.getBody())
.consumeNextWith(dataBuffer -> {
byte[] resultBytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(resultBytes);
assertArrayEquals("name+1=value+1&name+2=value+2%2B1&name+2=value+2%2B2&name+3".getBytes(StandardCharsets.UTF_8),
resultBytes);
})
.expectComplete()
.verify();
}
@Test
public void ofDataBuffers() throws Exception {
DefaultDataBufferFactory factory = new DefaultDataBufferFactory();