CodecConfigurer implementation refactoring

See gh-24124
This commit is contained in:
Rossen Stoyanchev 2019-12-12 17:01:01 +00:00
parent fa8f08391f
commit 9d65830133
9 changed files with 232 additions and 128 deletions

View File

@ -95,6 +95,8 @@ public interface ClientCodecConfigurer extends CodecConfigurer {
* <p>By default if this is not set, and Jackson is available, the * <p>By default if this is not set, and Jackson is available, the
* {@link #jackson2JsonDecoder} override is used instead. Use this property * {@link #jackson2JsonDecoder} override is used instead. Use this property
* if you want to further customize the SSE decoder. * if you want to further customize the SSE decoder.
* <p>Note that {@link #maxInMemorySize(int)}, if configured, will be
* applied to the given decoder.
* @param decoder the decoder to use * @param decoder the decoder to use
*/ */
void serverSentEventDecoder(Decoder<?> decoder); void serverSentEventDecoder(Decoder<?> decoder);

View File

@ -109,6 +109,8 @@ public interface CodecConfigurer {
/** /**
* Override the default Jackson JSON {@code Decoder}. * Override the default Jackson JSON {@code Decoder}.
* <p>Note that {@link #maxInMemorySize(int)}, if configured, will be
* applied to the given decoder.
* @param decoder the decoder instance to use * @param decoder the decoder instance to use
* @see org.springframework.http.codec.json.Jackson2JsonDecoder * @see org.springframework.http.codec.json.Jackson2JsonDecoder
*/ */
@ -123,6 +125,8 @@ public interface CodecConfigurer {
/** /**
* Override the default Protobuf {@code Decoder}. * Override the default Protobuf {@code Decoder}.
* <p>Note that {@link #maxInMemorySize(int)}, if configured, will be
* applied to the given decoder.
* @param decoder the decoder instance to use * @param decoder the decoder instance to use
* @since 5.1 * @since 5.1
* @see org.springframework.http.codec.protobuf.ProtobufDecoder * @see org.springframework.http.codec.protobuf.ProtobufDecoder
@ -140,6 +144,8 @@ public interface CodecConfigurer {
/** /**
* Override the default JAXB2 {@code Decoder}. * Override the default JAXB2 {@code Decoder}.
* <p>Note that {@link #maxInMemorySize(int)}, if configured, will be
* applied to the given decoder.
* @param decoder the decoder instance to use * @param decoder the decoder instance to use
* @since 5.1.3 * @since 5.1.3
* @see org.springframework.http.codec.xml.Jaxb2XmlDecoder * @see org.springframework.http.codec.xml.Jaxb2XmlDecoder
@ -245,7 +251,8 @@ public interface CodecConfigurer {
* Whether to log form data at DEBUG level, and headers at TRACE level. * Whether to log form data at DEBUG level, and headers at TRACE level.
* Both may contain sensitive information. * Both may contain sensitive information.
*/ */
boolean isEnableLoggingRequestDetails(); @Nullable
Boolean isEnableLoggingRequestDetails();
} }
} }

View File

@ -91,6 +91,9 @@ public interface ServerCodecConfigurer extends CodecConfigurer {
* MultipartHttpMessageReader} created with an instance of * MultipartHttpMessageReader} created with an instance of
* {@link org.springframework.http.codec.multipart.SynchronossPartHttpMessageReader * {@link org.springframework.http.codec.multipart.SynchronossPartHttpMessageReader
* SynchronossPartHttpMessageReader}. * SynchronossPartHttpMessageReader}.
* <p>Note that {@link #maxInMemorySize(int)} and/or
* {@link #enableLoggingRequestDetails(boolean)}, if configured, will be
* applied to the given reader, if applicable.
* @param reader the message reader to use for multipart requests. * @param reader the message reader to use for multipart requests.
* @since 5.1.11 * @since 5.1.11
*/ */

View File

@ -149,6 +149,16 @@ public class MultipartHttpMessageWriter extends LoggingCodecSupport
return Collections.unmodifiableList(this.partWriters); return Collections.unmodifiableList(this.partWriters);
} }
/**
* Return the configured form writer.
* @since 5.1.13
*/
@Nullable
public HttpMessageWriter<MultiValueMap<String, String>> getFormWriter() {
return this.formWriter;
}
/** /**
* Set the character set to use for part headers such as * Set the character set to use for part headers such as
* "Content-Disposition" (and its filename parameter). * "Content-Disposition" (and its filename parameter).

View File

@ -36,15 +36,20 @@ import org.springframework.http.codec.CodecConfigurer;
import org.springframework.http.codec.DecoderHttpMessageReader; import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.EncoderHttpMessageWriter; import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.FormHttpMessageReader; import org.springframework.http.codec.FormHttpMessageReader;
import org.springframework.http.codec.FormHttpMessageWriter;
import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageReader; import org.springframework.http.codec.ResourceHttpMessageReader;
import org.springframework.http.codec.ResourceHttpMessageWriter; import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.ServerSentEventHttpMessageReader;
import org.springframework.http.codec.json.AbstractJackson2Decoder; import org.springframework.http.codec.json.AbstractJackson2Decoder;
import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder; import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.json.Jackson2SmileDecoder; import org.springframework.http.codec.json.Jackson2SmileDecoder;
import org.springframework.http.codec.json.Jackson2SmileEncoder; import org.springframework.http.codec.json.Jackson2SmileEncoder;
import org.springframework.http.codec.multipart.MultipartHttpMessageReader;
import org.springframework.http.codec.multipart.MultipartHttpMessageWriter;
import org.springframework.http.codec.multipart.SynchronossPartHttpMessageReader;
import org.springframework.http.codec.protobuf.ProtobufDecoder; import org.springframework.http.codec.protobuf.ProtobufDecoder;
import org.springframework.http.codec.protobuf.ProtobufEncoder; import org.springframework.http.codec.protobuf.ProtobufEncoder;
import org.springframework.http.codec.protobuf.ProtobufHttpMessageWriter; import org.springframework.http.codec.protobuf.ProtobufHttpMessageWriter;
@ -70,6 +75,8 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
private static final boolean protobufPresent; private static final boolean protobufPresent;
static final boolean synchronossMultipartPresent;
static { static {
ClassLoader classLoader = BaseCodecConfigurer.class.getClassLoader(); ClassLoader classLoader = BaseCodecConfigurer.class.getClassLoader();
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) && jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
@ -77,6 +84,7 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
jackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader); jackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);
jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader); jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader);
protobufPresent = ClassUtils.isPresent("com.google.protobuf.Message", classLoader); protobufPresent = ClassUtils.isPresent("com.google.protobuf.Message", classLoader);
synchronossMultipartPresent = ClassUtils.isPresent("org.synchronoss.cloud.nio.multipart.NioMultipartParser", classLoader);
} }
@ -101,7 +109,8 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
@Nullable @Nullable
private Integer maxInMemorySize; private Integer maxInMemorySize;
private boolean enableLoggingRequestDetails = false; @Nullable
private Boolean enableLoggingRequestDetails;
private boolean registerDefaults = true; private boolean registerDefaults = true;
@ -171,7 +180,8 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
} }
@Override @Override
public boolean isEnableLoggingRequestDetails() { @Nullable
public Boolean isEnableLoggingRequestDetails() {
return this.enableLoggingRequestDetails; return this.enableLoggingRequestDetails;
} }
@ -191,48 +201,107 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
return Collections.emptyList(); return Collections.emptyList();
} }
List<HttpMessageReader<?>> readers = new ArrayList<>(); List<HttpMessageReader<?>> readers = new ArrayList<>();
readers.add(new DecoderHttpMessageReader<>(init(new ByteArrayDecoder()))); addCodec(readers, new DecoderHttpMessageReader<>(new ByteArrayDecoder()));
readers.add(new DecoderHttpMessageReader<>(init(new ByteBufferDecoder()))); addCodec(readers, new DecoderHttpMessageReader<>(new ByteBufferDecoder()));
readers.add(new DecoderHttpMessageReader<>(init(new DataBufferDecoder()))); addCodec(readers, new DecoderHttpMessageReader<>(new DataBufferDecoder()));
readers.add(new ResourceHttpMessageReader(init(new ResourceDecoder()))); addCodec(readers, new ResourceHttpMessageReader(new ResourceDecoder()));
readers.add(new DecoderHttpMessageReader<>(init(StringDecoder.textPlainOnly()))); addCodec(readers, new DecoderHttpMessageReader<>(StringDecoder.textPlainOnly()));
if (protobufPresent) { if (protobufPresent) {
Decoder<?> decoder = this.protobufDecoder != null ? this.protobufDecoder : init(new ProtobufDecoder()); Decoder<?> decoder = this.protobufDecoder != null ? this.protobufDecoder : new ProtobufDecoder();
readers.add(new DecoderHttpMessageReader<>(decoder)); addCodec(readers, new DecoderHttpMessageReader<>(decoder));
} }
addCodec(readers, new FormHttpMessageReader());
FormHttpMessageReader formReader = new FormHttpMessageReader(); // client vs server..
if (this.maxInMemorySize != null) {
formReader.setMaxInMemorySize(this.maxInMemorySize);
}
formReader.setEnableLoggingRequestDetails(this.enableLoggingRequestDetails);
readers.add(formReader);
extendTypedReaders(readers); extendTypedReaders(readers);
return readers; return readers;
} }
private <T extends Decoder<?>> T init(T decoder) { /**
if (this.maxInMemorySize != null) { * Initialize a codec and add it to the List.
if (decoder instanceof AbstractDataBufferDecoder) { * @since 5.1.13
((AbstractDataBufferDecoder<?>) decoder).setMaxInMemorySize(this.maxInMemorySize); */
protected <T> void addCodec(List<T> codecs, T codec) {
initCodec(codec);
codecs.add(codec);
}
/**
* Apply {@link #maxInMemorySize()} and {@link #enableLoggingRequestDetails},
* if configured by the application, to the given codec , including any
* codec it contains.
*/
private void initCodec(@Nullable Object codec) {
if (codec instanceof DecoderHttpMessageReader) {
codec = ((DecoderHttpMessageReader) codec).getDecoder();
}
else if (codec instanceof ServerSentEventHttpMessageReader) {
codec = ((ServerSentEventHttpMessageReader) codec).getDecoder();
}
if (codec == null) {
return;
}
Integer size = this.maxInMemorySize;
if (size != null) {
if (codec instanceof AbstractDataBufferDecoder) {
((AbstractDataBufferDecoder<?>) codec).setMaxInMemorySize(size);
} }
if (decoder instanceof ProtobufDecoder) { if (protobufPresent) {
((ProtobufDecoder) decoder).setMaxMessageSize(this.maxInMemorySize); if (codec instanceof ProtobufDecoder) {
((ProtobufDecoder) codec).setMaxMessageSize(size);
}
} }
if (jackson2Present) { if (jackson2Present) {
if (decoder instanceof AbstractJackson2Decoder) { if (codec instanceof AbstractJackson2Decoder) {
((AbstractJackson2Decoder) decoder).setMaxInMemorySize(this.maxInMemorySize); ((AbstractJackson2Decoder) codec).setMaxInMemorySize(size);
} }
} }
if (jaxb2Present) { if (jaxb2Present) {
if (decoder instanceof Jaxb2XmlDecoder) { if (codec instanceof Jaxb2XmlDecoder) {
((Jaxb2XmlDecoder) decoder).setMaxInMemorySize(this.maxInMemorySize); ((Jaxb2XmlDecoder) codec).setMaxInMemorySize(size);
}
}
if (codec instanceof FormHttpMessageReader) {
((FormHttpMessageReader) codec).setMaxInMemorySize(size);
}
if (synchronossMultipartPresent) {
if (codec instanceof SynchronossPartHttpMessageReader) {
((SynchronossPartHttpMessageReader) codec).setMaxInMemorySize(size);
} }
} }
} }
return decoder;
Boolean enable = this.enableLoggingRequestDetails;
if (enable != null) {
if (codec instanceof FormHttpMessageReader) {
((FormHttpMessageReader) codec).setEnableLoggingRequestDetails(enable);
}
if (codec instanceof MultipartHttpMessageReader) {
((MultipartHttpMessageReader) codec).setEnableLoggingRequestDetails(enable);
}
if (synchronossMultipartPresent) {
if (codec instanceof SynchronossPartHttpMessageReader) {
((SynchronossPartHttpMessageReader) codec).setEnableLoggingRequestDetails(enable);
}
}
if (codec instanceof FormHttpMessageWriter) {
((FormHttpMessageWriter) codec).setEnableLoggingRequestDetails(enable);
}
if (codec instanceof MultipartHttpMessageWriter) {
((MultipartHttpMessageWriter) codec).setEnableLoggingRequestDetails(enable);
}
}
if (codec instanceof MultipartHttpMessageReader) {
initCodec(((MultipartHttpMessageReader) codec).getPartReader());
}
else if (codec instanceof MultipartHttpMessageWriter) {
initCodec(((MultipartHttpMessageWriter) codec).getFormWriter());
}
} }
/** /**
@ -250,16 +319,19 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
} }
List<HttpMessageReader<?>> readers = new ArrayList<>(); List<HttpMessageReader<?>> readers = new ArrayList<>();
if (jackson2Present) { if (jackson2Present) {
readers.add(new DecoderHttpMessageReader<>(init(getJackson2JsonDecoder()))); addCodec(readers, new DecoderHttpMessageReader<>(getJackson2JsonDecoder()));
} }
if (jackson2SmilePresent) { if (jackson2SmilePresent) {
readers.add(new DecoderHttpMessageReader<>(init(new Jackson2SmileDecoder()))); addCodec(readers, new DecoderHttpMessageReader<>(new Jackson2SmileDecoder()));
} }
if (jaxb2Present) { if (jaxb2Present) {
Decoder<?> decoder = this.jaxb2Decoder != null ? this.jaxb2Decoder : init(new Jaxb2XmlDecoder()); Decoder<?> decoder = this.jaxb2Decoder != null ? this.jaxb2Decoder : new Jaxb2XmlDecoder();
readers.add(new DecoderHttpMessageReader<>(decoder)); addCodec(readers, new DecoderHttpMessageReader<>(decoder));
} }
// client vs server..
extendObjectReaders(readers); extendObjectReaders(readers);
return readers; return readers;
} }
@ -276,9 +348,9 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
if (!this.registerDefaults) { if (!this.registerDefaults) {
return Collections.emptyList(); return Collections.emptyList();
} }
List<HttpMessageReader<?>> result = new ArrayList<>(); List<HttpMessageReader<?>> readers = new ArrayList<>();
result.add(new DecoderHttpMessageReader<>(init(StringDecoder.allMimeTypes()))); addCodec(readers, new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes()));
return result; return readers;
} }
/** /**
@ -365,11 +437,17 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
// Accessors for use in subclasses... // Accessors for use in subclasses...
protected Decoder<?> getJackson2JsonDecoder() { protected Decoder<?> getJackson2JsonDecoder() {
return (this.jackson2JsonDecoder != null ? this.jackson2JsonDecoder : new Jackson2JsonDecoder()); if (this.jackson2JsonDecoder == null) {
this.jackson2JsonDecoder = new Jackson2JsonDecoder();
}
return this.jackson2JsonDecoder;
} }
protected Encoder<?> getJackson2JsonEncoder() { protected Encoder<?> getJackson2JsonEncoder() {
return (this.jackson2JsonEncoder != null ? this.jackson2JsonEncoder : new Jackson2JsonEncoder()); if (this.jackson2JsonEncoder == null) {
this.jackson2JsonEncoder = new Jackson2JsonEncoder();
}
return this.jackson2JsonEncoder;
} }
} }

View File

@ -95,24 +95,17 @@ class ClientDefaultCodecsImpl extends BaseDefaultCodecs implements ClientCodecCo
@Override @Override
protected void extendObjectReaders(List<HttpMessageReader<?>> objectReaders) { protected void extendObjectReaders(List<HttpMessageReader<?>> objectReaders) {
objectReaders.add(new ServerSentEventHttpMessageReader(getSseDecoder()));
}
@Nullable Decoder<?> decoder = (this.sseDecoder != null ?
private Decoder<?> getSseDecoder() { this.sseDecoder :
return (this.sseDecoder != null ? this.sseDecoder : jackson2Present ? getJackson2JsonDecoder() : null); jackson2Present ? getJackson2JsonDecoder() : null);
addCodec(objectReaders, new ServerSentEventHttpMessageReader(decoder));
} }
@Override @Override
protected void extendTypedWriters(List<HttpMessageWriter<?>> typedWriters) { protected void extendTypedWriters(List<HttpMessageWriter<?>> typedWriters) {
addCodec(typedWriters, new MultipartHttpMessageWriter(getPartWriters(), new FormHttpMessageWriter()));
FormHttpMessageWriter formWriter = new FormHttpMessageWriter();
formWriter.setEnableLoggingRequestDetails(isEnableLoggingRequestDetails());
MultipartHttpMessageWriter multipartWriter = new MultipartHttpMessageWriter(getPartWriters(), formWriter);
multipartWriter.setEnableLoggingRequestDetails(isEnableLoggingRequestDetails());
typedWriters.add(multipartWriter);
} }
private List<HttpMessageWriter<?>> getPartWriters() { private List<HttpMessageWriter<?>> getPartWriters() {

View File

@ -25,7 +25,6 @@ import org.springframework.http.codec.ServerSentEventHttpMessageWriter;
import org.springframework.http.codec.multipart.MultipartHttpMessageReader; import org.springframework.http.codec.multipart.MultipartHttpMessageReader;
import org.springframework.http.codec.multipart.SynchronossPartHttpMessageReader; import org.springframework.http.codec.multipart.SynchronossPartHttpMessageReader;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/** /**
* Default implementation of {@link ServerCodecConfigurer.ServerDefaultCodecs}. * Default implementation of {@link ServerCodecConfigurer.ServerDefaultCodecs}.
@ -34,11 +33,6 @@ import org.springframework.util.ClassUtils;
*/ */
class ServerDefaultCodecsImpl extends BaseDefaultCodecs implements ServerCodecConfigurer.ServerDefaultCodecs { class ServerDefaultCodecsImpl extends BaseDefaultCodecs implements ServerCodecConfigurer.ServerDefaultCodecs {
private static final boolean synchronossMultipartPresent =
ClassUtils.isPresent("org.synchronoss.cloud.nio.multipart.NioMultipartParser",
DefaultServerCodecConfigurer.class.getClassLoader());
@Nullable @Nullable
private HttpMessageReader<?> multipartReader; private HttpMessageReader<?> multipartReader;
@ -70,23 +64,13 @@ class ServerDefaultCodecsImpl extends BaseDefaultCodecs implements ServerCodecCo
@Override @Override
protected void extendTypedReaders(List<HttpMessageReader<?>> typedReaders) { protected void extendTypedReaders(List<HttpMessageReader<?>> typedReaders) {
if (this.multipartReader != null) { if (this.multipartReader != null) {
typedReaders.add(this.multipartReader); addCodec(typedReaders, this.multipartReader);
return; return;
} }
if (synchronossMultipartPresent) { if (synchronossMultipartPresent) {
boolean enable = isEnableLoggingRequestDetails();
SynchronossPartHttpMessageReader partReader = new SynchronossPartHttpMessageReader(); SynchronossPartHttpMessageReader partReader = new SynchronossPartHttpMessageReader();
Integer size = maxInMemorySize(); addCodec(typedReaders, partReader);
if (size != null) { addCodec(typedReaders, new MultipartHttpMessageReader(partReader));
partReader.setMaxInMemorySize(size);
}
partReader.setEnableLoggingRequestDetails(enable);
typedReaders.add(partReader);
MultipartHttpMessageReader reader = new MultipartHttpMessageReader(partReader);
reader.setEnableLoggingRequestDetails(enable);
typedReaders.add(reader);
} }
} }

View File

@ -22,7 +22,6 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
@ -37,6 +36,7 @@ import org.springframework.core.codec.DataBufferDecoder;
import org.springframework.core.codec.DataBufferEncoder; import org.springframework.core.codec.DataBufferEncoder;
import org.springframework.core.codec.Decoder; import org.springframework.core.codec.Decoder;
import org.springframework.core.codec.Encoder; import org.springframework.core.codec.Encoder;
import org.springframework.core.codec.ResourceDecoder;
import org.springframework.core.codec.StringDecoder; import org.springframework.core.codec.StringDecoder;
import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@ -44,6 +44,7 @@ import org.springframework.http.codec.ClientCodecConfigurer;
import org.springframework.http.codec.DecoderHttpMessageReader; import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.EncoderHttpMessageWriter; import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.FormHttpMessageReader; import org.springframework.http.codec.FormHttpMessageReader;
import org.springframework.http.codec.FormHttpMessageWriter;
import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageReader; import org.springframework.http.codec.ResourceHttpMessageReader;
@ -116,12 +117,45 @@ public class ClientCodecConfigurerTests {
Jackson2JsonDecoder decoder = new Jackson2JsonDecoder(); Jackson2JsonDecoder decoder = new Jackson2JsonDecoder();
this.configurer.defaultCodecs().jackson2JsonDecoder(decoder); this.configurer.defaultCodecs().jackson2JsonDecoder(decoder);
assertThat(this.configurer.getReaders().stream() List<HttpMessageReader<?>> readers = this.configurer.getReaders();
.filter(reader -> ServerSentEventHttpMessageReader.class.equals(reader.getClass())) assertThat(findCodec(readers, ServerSentEventHttpMessageReader.class).getDecoder()).isSameAs(decoder);
.map(reader -> (ServerSentEventHttpMessageReader) reader) }
.findFirst()
.map(ServerSentEventHttpMessageReader::getDecoder) @Test
.filter(e -> e == decoder).orElse(null)).isSameAs(decoder); public void maxInMemorySize() {
int size = 99;
this.configurer.defaultCodecs().maxInMemorySize(size);
List<HttpMessageReader<?>> readers = this.configurer.getReaders();
assertThat(readers.size()).isEqualTo(12);
assertThat(((ByteArrayDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((ByteBufferDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((DataBufferDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((ResourceDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((StringDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((ProtobufDecoder) getNextDecoder(readers)).getMaxMessageSize()).isEqualTo(size);
assertThat(((FormHttpMessageReader) nextReader(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((Jackson2JsonDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((Jackson2SmileDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((Jaxb2XmlDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
ServerSentEventHttpMessageReader reader = (ServerSentEventHttpMessageReader) nextReader(readers);
assertThat(((Jackson2JsonDecoder) reader.getDecoder()).getMaxInMemorySize()).isEqualTo(size);
assertThat(((StringDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
}
@Test
public void enableLoggingRequestDetails() {
this.configurer.defaultCodecs().enableLoggingRequestDetails(true);
List<HttpMessageWriter<?>> writers = this.configurer.getWriters();
MultipartHttpMessageWriter multipartWriter = findCodec(writers, MultipartHttpMessageWriter.class);
assertThat(multipartWriter.isEnableLoggingRequestDetails()).isTrue();
FormHttpMessageWriter formWriter = (FormHttpMessageWriter) multipartWriter.getFormWriter();
assertThat(formWriter).isNotNull();
assertThat(formWriter.isEnableLoggingRequestDetails()).isTrue();
} }
@Test @Test
@ -135,49 +169,42 @@ public class ClientCodecConfigurerTests {
// Clone has the customizations // Clone has the customizations
Decoder<?> sseDecoder = clone.getReaders().stream() Decoder<?> sseDecoder = findCodec(clone.getReaders(), ServerSentEventHttpMessageReader.class).getDecoder();
.filter(reader -> reader instanceof ServerSentEventHttpMessageReader) List<HttpMessageWriter<?>> writers = findCodec(clone.getWriters(), MultipartHttpMessageWriter.class).getPartWriters();
.map(reader -> ((ServerSentEventHttpMessageReader) reader).getDecoder())
.findFirst()
.get();
List<HttpMessageWriter<?>> multipartWriters = clone.getWriters().stream()
.filter(writer -> writer instanceof MultipartHttpMessageWriter)
.flatMap(writer -> ((MultipartHttpMessageWriter) writer).getPartWriters().stream())
.collect(Collectors.toList());
assertThat(sseDecoder).isSameAs(jackson2Decoder); assertThat(sseDecoder).isSameAs(jackson2Decoder);
assertThat(multipartWriters).hasSize(2); assertThat(writers).hasSize(2);
// Original does not have the customizations // Original does not have the customizations
sseDecoder = this.configurer.getReaders().stream() sseDecoder = findCodec(this.configurer.getReaders(), ServerSentEventHttpMessageReader.class).getDecoder();
.filter(reader -> reader instanceof ServerSentEventHttpMessageReader) writers = findCodec(this.configurer.getWriters(), MultipartHttpMessageWriter.class).getPartWriters();
.map(reader -> ((ServerSentEventHttpMessageReader) reader).getDecoder())
.findFirst()
.get();
multipartWriters = this.configurer.getWriters().stream()
.filter(writer -> writer instanceof MultipartHttpMessageWriter)
.flatMap(writer -> ((MultipartHttpMessageWriter) writer).getPartWriters().stream())
.collect(Collectors.toList());
assertThat(sseDecoder).isNotSameAs(jackson2Decoder); assertThat(sseDecoder).isNotSameAs(jackson2Decoder);
assertThat(multipartWriters).hasSize(10); assertThat(writers).hasSize(10);
} }
private Decoder<?> getNextDecoder(List<HttpMessageReader<?>> readers) { private Decoder<?> getNextDecoder(List<HttpMessageReader<?>> readers) {
HttpMessageReader<?> reader = readers.get(this.index.getAndIncrement()); HttpMessageReader<?> reader = readers.get(this.index.getAndIncrement());
assertThat(reader.getClass()).isEqualTo(DecoderHttpMessageReader.class); assertThat(reader).isInstanceOf(DecoderHttpMessageReader.class);
return ((DecoderHttpMessageReader<?>) reader).getDecoder(); return ((DecoderHttpMessageReader<?>) reader).getDecoder();
} }
private HttpMessageReader<?> nextReader(List<HttpMessageReader<?>> readers) {
return readers.get(this.index.getAndIncrement());
}
private Encoder<?> getNextEncoder(List<HttpMessageWriter<?>> writers) { private Encoder<?> getNextEncoder(List<HttpMessageWriter<?>> writers) {
HttpMessageWriter<?> writer = writers.get(this.index.getAndIncrement()); HttpMessageWriter<?> writer = writers.get(this.index.getAndIncrement());
assertThat(writer.getClass()).isEqualTo(EncoderHttpMessageWriter.class); assertThat(writer.getClass()).isEqualTo(EncoderHttpMessageWriter.class);
return ((EncoderHttpMessageWriter<?>) writer).getEncoder(); return ((EncoderHttpMessageWriter<?>) writer).getEncoder();
} }
@SuppressWarnings("unchecked")
private <T> T findCodec(List<?> codecs, Class<T> type) {
return (T) codecs.stream().filter(type::isInstance).findFirst().get();
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void assertStringDecoder(Decoder<?> decoder, boolean textOnly) { private void assertStringDecoder(Decoder<?> decoder, boolean textOnly) {
assertThat(decoder.getClass()).isEqualTo(StringDecoder.class); assertThat(decoder.getClass()).isEqualTo(StringDecoder.class);

View File

@ -134,11 +134,7 @@ public class ServerCodecConfigurerTests {
assertThat(((ByteArrayDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size); assertThat(((ByteArrayDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((ByteBufferDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size); assertThat(((ByteBufferDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((DataBufferDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size); assertThat(((DataBufferDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((ResourceDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
ResourceHttpMessageReader resourceReader = (ResourceHttpMessageReader) nextReader(readers);
ResourceDecoder decoder = (ResourceDecoder) resourceReader.getDecoder();
assertThat(decoder.getMaxInMemorySize()).isEqualTo(size);
assertThat(((StringDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size); assertThat(((StringDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((ProtobufDecoder) getNextDecoder(readers)).getMaxMessageSize()).isEqualTo(size); assertThat(((ProtobufDecoder) getNextDecoder(readers)).getMaxMessageSize()).isEqualTo(size);
assertThat(((FormHttpMessageReader) nextReader(readers)).getMaxInMemorySize()).isEqualTo(size); assertThat(((FormHttpMessageReader) nextReader(readers)).getMaxInMemorySize()).isEqualTo(size);
@ -154,6 +150,20 @@ public class ServerCodecConfigurerTests {
assertThat(((StringDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size); assertThat(((StringDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
} }
@Test
public void enableRequestLoggingDetails() {
this.configurer.defaultCodecs().enableLoggingRequestDetails(true);
List<HttpMessageReader<?>> readers = this.configurer.getReaders();
assertThat(findCodec(readers, FormHttpMessageReader.class).isEnableLoggingRequestDetails()).isTrue();
MultipartHttpMessageReader multipartReader = findCodec(readers, MultipartHttpMessageReader.class);
assertThat(multipartReader.isEnableLoggingRequestDetails()).isTrue();
SynchronossPartHttpMessageReader reader = (SynchronossPartHttpMessageReader) multipartReader.getPartReader();
assertThat(reader.isEnableLoggingRequestDetails()).isTrue();
}
@Test @Test
public void cloneConfigurer() { public void cloneConfigurer() {
ServerCodecConfigurer clone = this.configurer.clone(); ServerCodecConfigurer clone = this.configurer.clone();
@ -165,42 +175,27 @@ public class ServerCodecConfigurerTests {
// Clone has the customizations // Clone has the customizations
HttpMessageReader<?> actualReader = clone.getReaders().stream() HttpMessageReader<?> actualReader =
.filter(r -> r instanceof MultipartHttpMessageReader) findCodec(clone.getReaders(), MultipartHttpMessageReader.class);
.findFirst()
.get();
Encoder<?> actualEncoder = clone.getWriters().stream()
.filter(writer -> writer instanceof ServerSentEventHttpMessageWriter)
.map(writer -> ((ServerSentEventHttpMessageWriter) writer).getEncoder())
.findFirst()
.get();
ServerSentEventHttpMessageWriter actualWriter =
findCodec(clone.getWriters(), ServerSentEventHttpMessageWriter.class);
assertThat(actualReader).isSameAs(reader); assertThat(actualReader).isSameAs(reader);
assertThat(actualEncoder).isSameAs(encoder); assertThat(actualWriter.getEncoder()).isSameAs(encoder);
// Original does not have the customizations // Original does not have the customizations
actualReader = this.configurer.getReaders().stream() actualReader = findCodec(this.configurer.getReaders(), MultipartHttpMessageReader.class);
.filter(r -> r instanceof MultipartHttpMessageReader) actualWriter = findCodec(this.configurer.getWriters(), ServerSentEventHttpMessageWriter.class);
.findFirst()
.get();
actualEncoder = this.configurer.getWriters().stream()
.filter(writer -> writer instanceof ServerSentEventHttpMessageWriter)
.map(writer -> ((ServerSentEventHttpMessageWriter) writer).getEncoder())
.findFirst()
.get();
assertThat(actualReader).isNotSameAs(reader); assertThat(actualReader).isNotSameAs(reader);
assertThat(actualEncoder).isNotSameAs(encoder); assertThat(actualWriter.getEncoder()).isNotSameAs(encoder);
} }
private Decoder<?> getNextDecoder(List<HttpMessageReader<?>> readers) { private Decoder<?> getNextDecoder(List<HttpMessageReader<?>> readers) {
HttpMessageReader<?> reader = nextReader(readers); HttpMessageReader<?> reader = nextReader(readers);
assertThat(reader.getClass()).isEqualTo(DecoderHttpMessageReader.class); assertThat(reader).isInstanceOf(DecoderHttpMessageReader.class);
return ((DecoderHttpMessageReader<?>) reader).getDecoder(); return ((DecoderHttpMessageReader<?>) reader).getDecoder();
} }
@ -214,6 +209,11 @@ public class ServerCodecConfigurerTests {
return ((EncoderHttpMessageWriter<?>) writer).getEncoder(); return ((EncoderHttpMessageWriter<?>) writer).getEncoder();
} }
@SuppressWarnings("unchecked")
private <T> T findCodec(List<?> codecs, Class<T> type) {
return (T) codecs.stream().filter(type::isInstance).findFirst().get();
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void assertStringDecoder(Decoder<?> decoder, boolean textOnly) { private void assertStringDecoder(Decoder<?> decoder, boolean textOnly) {
assertThat(decoder.getClass()).isEqualTo(StringDecoder.class); assertThat(decoder.getClass()).isEqualTo(StringDecoder.class);