syncBody better differentiates plain vs multipart forms

FromHttpMessageWriter and MultipartHttpMessageWriter both support
MultiValueMap except the former supports String values only. This
presents an issue since either full generic type information must be
provided, which is cumbersome on the client side, or if left out there
is no good way to order the writers to make a proper decision.

This commit:

- refines the canWrite behavior of   to not a
accept MultiValueMap without proper generic information unless the
MediaType is explicitly set providing a strong hint.

- modifies MultipartHttpMessageWriter to be configured with a
FormHttpMessageWriter so it can write both plan and multipart data with
the ability to properly differentiate based on actual map values.

Issue: SPR-16131
This commit is contained in:
Rossen Stoyanchev
2017-10-31 08:54:19 -04:00
parent e5c8dc0d65
commit 8083eaae54
8 changed files with 161 additions and 65 deletions

View File

@@ -27,7 +27,9 @@ import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author Sebastien Deleuze
@@ -43,17 +45,18 @@ public class FormHttpMessageWriterTests {
ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, String.class),
MediaType.APPLICATION_FORM_URLENCODED));
// No generic information
assertTrue(this.writer.canWrite(
ResolvableType.forInstance(new LinkedMultiValueMap<String, String>()),
MediaType.APPLICATION_FORM_URLENCODED));
assertFalse(this.writer.canWrite(
ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, Object.class),
MediaType.APPLICATION_FORM_URLENCODED));
null));
assertFalse(this.writer.canWrite(
ResolvableType.forClassWithGenerics(MultiValueMap.class, Object.class, String.class),
MediaType.APPLICATION_FORM_URLENCODED));
null));
assertFalse(this.writer.canWrite(
ResolvableType.forClassWithGenerics(Map.class, String.class, String.class),

View File

@@ -70,7 +70,7 @@ public class MultipartHttpMessageWriterTests {
assertFalse(this.writer.canWrite(
ResolvableType.forClassWithGenerics(Map.class, String.class, Object.class),
MediaType.MULTIPART_FORM_DATA));
assertFalse(this.writer.canWrite(
assertTrue(this.writer.canWrite(
ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, Object.class),
MediaType.APPLICATION_FORM_URLENCODED));
}

View File

@@ -42,7 +42,6 @@ import org.springframework.http.MediaType;
import org.springframework.http.codec.ClientCodecConfigurer;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.FormHttpMessageWriter;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageWriter;
@@ -56,8 +55,11 @@ import org.springframework.http.codec.xml.Jaxb2XmlDecoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.util.MimeTypeUtils;
import static org.junit.Assert.*;
import static org.springframework.core.ResolvableType.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.springframework.core.ResolvableType.forClass;
/**
* Unit tests for {@link ClientCodecConfigurer}.
@@ -90,13 +92,12 @@ public class ClientCodecConfigurerTests {
@Test
public void defaultWriters() {
List<HttpMessageWriter<?>> writers = this.configurer.getWriters();
assertEquals(11, writers.size());
assertEquals(10, writers.size());
assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass());
assertEquals(ByteBufferEncoder.class, getNextEncoder(writers).getClass());
assertEquals(DataBufferEncoder.class, getNextEncoder(writers).getClass());
assertEquals(ResourceHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
assertStringEncoder(getNextEncoder(writers), true);
assertEquals(FormHttpMessageWriter.class, writers.get(this.index.getAndIncrement()).getClass());
assertEquals(MultipartHttpMessageWriter.class, writers.get(this.index.getAndIncrement()).getClass());
assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jackson2SmileEncoder.class, getNextEncoder(writers).getClass());