diff --git a/spring-web/src/main/java/org/springframework/http/codec/ClientCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/ClientCodecConfigurer.java index 070b0610ee1f..cfba0520ea88 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/ClientCodecConfigurer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/ClientCodecConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -17,7 +17,6 @@ package org.springframework.http.codec; import org.springframework.core.codec.Decoder; -import org.springframework.core.codec.Encoder; /** * Extension of {@link CodecConfigurer} for HTTP message reader and writer @@ -83,13 +82,6 @@ static ClientCodecConfigurer create() { */ interface ClientDefaultCodecs extends DefaultCodecs { - /** - * Configure encoders or writers for use with - * {@link org.springframework.http.codec.multipart.MultipartHttpMessageWriter - * MultipartHttpMessageWriter}. - */ - MultipartCodecs multipartCodecs(); - /** * Configure the {@code Decoder} to use for Server-Sent Events. *

By default if this is not set, and Jackson is available, the @@ -102,26 +94,4 @@ interface ClientDefaultCodecs extends DefaultCodecs { void serverSentEventDecoder(Decoder decoder); } - - /** - * Registry and container for multipart HTTP message writers. - */ - interface MultipartCodecs { - - /** - * Add a Part {@code Encoder}, internally wrapped with - * {@link EncoderHttpMessageWriter}. - * @param encoder the encoder to add - */ - MultipartCodecs encoder(Encoder encoder); - - /** - * Add a Part {@link HttpMessageWriter}. For writers of type - * {@link EncoderHttpMessageWriter} consider using the shortcut - * {@link #encoder(Encoder)} instead. - * @param writer the writer to add - */ - MultipartCodecs writer(HttpMessageWriter writer); - } - } diff --git a/spring-web/src/main/java/org/springframework/http/codec/CodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/CodecConfigurer.java index a27b0709a3aa..a5906a49b697 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/CodecConfigurer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/CodecConfigurer.java @@ -258,6 +258,24 @@ interface DefaultCodecs { * @since 5.1 */ void enableLoggingRequestDetails(boolean enable); + + /** + * Configure encoders or writers for use with + * {@link org.springframework.http.codec.multipart.MultipartHttpMessageWriter + * MultipartHttpMessageWriter}. + * @since 6.0.3 + */ + MultipartCodecs multipartCodecs(); + + /** + * Configure the {@code HttpMessageReader} to use for multipart requests. + *

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. + * @since 6.0.3 + */ + void multipartReader(HttpMessageReader reader); } @@ -389,4 +407,27 @@ interface DefaultCodecConfig { Boolean isEnableLoggingRequestDetails(); } + + /** + * Registry and container for multipart HTTP message writers. + * @since 6.0.3 + */ + interface MultipartCodecs { + + /** + * Add a Part {@code Encoder}, internally wrapped with + * {@link EncoderHttpMessageWriter}. + * @param encoder the encoder to add + */ + MultipartCodecs encoder(Encoder encoder); + + /** + * Add a Part {@link HttpMessageWriter}. For writers of type + * {@link EncoderHttpMessageWriter} consider using the shortcut + * {@link #encoder(Encoder)} instead. + * @param writer the writer to add + */ + MultipartCodecs writer(HttpMessageWriter writer); + } + } diff --git a/spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java index c6f9222a19c0..767ab738e0d2 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -82,16 +82,6 @@ static ServerCodecConfigurer create() { */ interface ServerDefaultCodecs extends DefaultCodecs { - /** - * Configure the {@code HttpMessageReader} to use for multipart requests. - *

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. - * @since 5.1.11 - */ - void multipartReader(HttpMessageReader reader); - /** * Configure the {@code Encoder} to use for Server-Sent Events. *

By default if this is not set, and Jackson is available, the diff --git a/spring-web/src/main/java/org/springframework/http/codec/multipart/MultipartHttpMessageWriter.java b/spring-web/src/main/java/org/springframework/http/codec/multipart/MultipartHttpMessageWriter.java index 777b5991ab86..b4fca60dd935 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/multipart/MultipartHttpMessageWriter.java +++ b/spring-web/src/main/java/org/springframework/http/codec/multipart/MultipartHttpMessageWriter.java @@ -79,7 +79,7 @@ public class MultipartHttpMessageWriter extends MultipartWriterSupport private static final Map DEFAULT_HINTS = Hints.from(Hints.SUPPRESS_LOGGING_HINT, true); - private final List> partWriters; + private final Supplier>> partWritersSupplier; @Nullable private final HttpMessageWriter> formWriter; @@ -112,8 +112,23 @@ public MultipartHttpMessageWriter(List> partWriters) { public MultipartHttpMessageWriter(List> partWriters, @Nullable HttpMessageWriter> formWriter) { + this(() -> partWriters, formWriter); + } + + /** + * Constructor with a supplier for an explicit list of writers for + * serializing parts and a writer for plain form data to fall back when + * no media type is specified and the actual map consists of String + * values only. + * @param partWritersSupplier the supplier for writers for serializing parts + * @param formWriter the fallback writer for form data, {@code null} by default + * @since 6.0.3 + */ + public MultipartHttpMessageWriter(Supplier>> partWritersSupplier, + @Nullable HttpMessageWriter> formWriter) { + super(initMediaTypes(formWriter)); - this.partWriters = partWriters; + this.partWritersSupplier = partWritersSupplier; this.formWriter = formWriter; } @@ -131,7 +146,7 @@ private static List initMediaTypes(@Nullable HttpMessageWriter for * @since 5.0.7 */ public List> getPartWriters() { - return Collections.unmodifiableList(this.partWriters); + return Collections.unmodifiableList(this.partWritersSupplier.get()); } @@ -264,8 +279,8 @@ else if (resolvableType.resolve() == Resource.class) { MediaType contentType = headers.getContentType(); - final ResolvableType finalBodyType = resolvableType; - Optional> writer = this.partWriters.stream() + ResolvableType finalBodyType = resolvableType; + Optional> writer = this.partWritersSupplier.get().stream() .filter(partWriter -> partWriter.canWrite(finalBodyType, contentType)) .findFirst(); diff --git a/spring-web/src/main/java/org/springframework/http/codec/support/BaseCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/support/BaseCodecConfigurer.java index 4eed384a6413..3b7b4ddb2e23 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/support/BaseCodecConfigurer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/support/BaseCodecConfigurer.java @@ -55,6 +55,7 @@ abstract class BaseCodecConfigurer implements CodecConfigurer { Assert.notNull(defaultCodecs, "'defaultCodecs' is required"); this.defaultCodecs = defaultCodecs; this.customCodecs = new DefaultCustomCodecs(); + this.defaultCodecs.setPartWritersSupplier(this::getWriters); } /** @@ -64,6 +65,7 @@ abstract class BaseCodecConfigurer implements CodecConfigurer { protected BaseCodecConfigurer(BaseCodecConfigurer other) { this.defaultCodecs = other.cloneDefaultCodecs(); this.customCodecs = new DefaultCustomCodecs(other.customCodecs); + this.defaultCodecs.setPartWritersSupplier(this::getWriters); } /** diff --git a/spring-web/src/main/java/org/springframework/http/codec/support/BaseDefaultCodecs.java b/spring-web/src/main/java/org/springframework/http/codec/support/BaseDefaultCodecs.java index 9cfe0f3d7fb6..05c4c0f4a4d1 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/support/BaseDefaultCodecs.java +++ b/spring-web/src/main/java/org/springframework/http/codec/support/BaseDefaultCodecs.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.Map; import java.util.function.Consumer; +import java.util.function.Supplier; import org.springframework.core.codec.AbstractDataBufferDecoder; import org.springframework.core.codec.ByteArrayDecoder; @@ -62,6 +63,8 @@ import org.springframework.http.codec.multipart.MultipartHttpMessageReader; import org.springframework.http.codec.multipart.MultipartHttpMessageWriter; import org.springframework.http.codec.multipart.PartEventHttpMessageReader; +import org.springframework.http.codec.multipart.PartEventHttpMessageWriter; +import org.springframework.http.codec.multipart.PartHttpMessageWriter; import org.springframework.http.codec.protobuf.KotlinSerializationProtobufDecoder; import org.springframework.http.codec.protobuf.KotlinSerializationProtobufEncoder; import org.springframework.http.codec.protobuf.ProtobufDecoder; @@ -160,6 +163,15 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure @Nullable private Encoder kotlinSerializationProtobufEncoder; + @Nullable + private DefaultMultipartCodecs multipartCodecs; + + @Nullable + private Supplier>> partWritersSupplier; + + @Nullable + private HttpMessageReader multipartReader; + @Nullable private Consumer codecConsumer; @@ -224,6 +236,9 @@ protected BaseDefaultCodecs(BaseDefaultCodecs other) { this.kotlinSerializationJsonEncoder = other.kotlinSerializationJsonEncoder; this.kotlinSerializationProtobufDecoder = other.kotlinSerializationProtobufDecoder; this.kotlinSerializationProtobufEncoder = other.kotlinSerializationProtobufEncoder; + this.multipartCodecs = other.multipartCodecs != null ? + new DefaultMultipartCodecs(other.multipartCodecs) : null; + this.multipartReader = other.multipartReader; this.codecConsumer = other.codecConsumer; this.maxInMemorySize = other.maxInMemorySize; this.enableLoggingRequestDetails = other.enableLoggingRequestDetails; @@ -351,6 +366,31 @@ public void enableLoggingRequestDetails(boolean enable) { } } + @Override + public CodecConfigurer.MultipartCodecs multipartCodecs() { + if (this.multipartCodecs == null) { + this.multipartCodecs = new DefaultMultipartCodecs(); + } + return this.multipartCodecs; + } + + @Override + public void multipartReader(HttpMessageReader multipartReader) { + this.multipartReader = multipartReader; + initTypedReaders(); + } + + /** + * Set a supplier for part writers to use when + * {@link #multipartCodecs()} are not explicitly configured. + * That's the same set of writers as for general except for the multipart + * writer itself. + */ + void setPartWritersSupplier(Supplier>> supplier) { + this.partWritersSupplier = supplier; + initTypedWriters(); + } + @Override @Nullable public Boolean isEnableLoggingRequestDetails() { @@ -405,6 +445,15 @@ else if (kotlinSerializationProtobufPresent) { (KotlinSerializationProtobufDecoder) this.kotlinSerializationProtobufDecoder : new KotlinSerializationProtobufDecoder())); } addCodec(this.typedReaders, new FormHttpMessageReader()); + if (this.multipartReader != null) { + addCodec(this.typedReaders, this.multipartReader); + } + else { + DefaultPartHttpMessageReader partReader = new DefaultPartHttpMessageReader(); + addCodec(this.typedReaders, partReader); + addCodec(this.typedReaders, new MultipartHttpMessageReader(partReader)); + } + addCodec(this.typedReaders, new PartEventHttpMessageReader()); // client vs server.. extendTypedReaders(this.typedReaders); @@ -641,9 +690,25 @@ final List> getBaseTypedWriters() { addCodec(writers, new ProtobufHttpMessageWriter(this.protobufEncoder != null ? (ProtobufEncoder) this.protobufEncoder : new ProtobufEncoder())); } + addCodec(writers, new MultipartHttpMessageWriter(this::getPartWriters, new FormHttpMessageWriter())); + addCodec(writers, new PartEventHttpMessageWriter()); + addCodec(writers, new PartHttpMessageWriter()); return writers; } + private List> getPartWriters() { + if (this.multipartCodecs != null) { + return this.multipartCodecs.getWriters(); + } + else if (this.partWritersSupplier != null) { + return this.partWritersSupplier.get(); + } + else { + return Collections.emptyList(); + } + } + + /** * Hook for client or server specific typed writers. */ @@ -766,4 +831,41 @@ protected Encoder getKotlinSerializationJsonEncoder() { return this.kotlinSerializationJsonEncoder; } + + /** + * Default implementation of {@link CodecConfigurer.MultipartCodecs}. + */ + protected class DefaultMultipartCodecs implements CodecConfigurer.MultipartCodecs { + + private final List> writers = new ArrayList<>(); + + + DefaultMultipartCodecs() { + } + + DefaultMultipartCodecs(DefaultMultipartCodecs other) { + this.writers.addAll(other.writers); + } + + + @Override + public CodecConfigurer.MultipartCodecs encoder(Encoder encoder) { + writer(new EncoderHttpMessageWriter<>(encoder)); + initTypedWriters(); + return this; + } + + @Override + public CodecConfigurer.MultipartCodecs writer(HttpMessageWriter writer) { + this.writers.add(writer); + initTypedWriters(); + return this; + } + + List> getWriters() { + return this.writers; + } + } + + } diff --git a/spring-web/src/main/java/org/springframework/http/codec/support/ClientDefaultCodecsImpl.java b/spring-web/src/main/java/org/springframework/http/codec/support/ClientDefaultCodecsImpl.java index c321682174b1..a494a74ccefe 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/support/ClientDefaultCodecsImpl.java +++ b/spring-web/src/main/java/org/springframework/http/codec/support/ClientDefaultCodecsImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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,21 +16,12 @@ package org.springframework.http.codec.support; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.function.Supplier; import org.springframework.core.codec.Decoder; -import org.springframework.core.codec.Encoder; import org.springframework.http.codec.ClientCodecConfigurer; -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.ServerSentEventHttpMessageReader; -import org.springframework.http.codec.multipart.MultipartHttpMessageWriter; -import org.springframework.http.codec.multipart.PartEventHttpMessageWriter; import org.springframework.lang.Nullable; /** @@ -40,47 +31,18 @@ */ class ClientDefaultCodecsImpl extends BaseDefaultCodecs implements ClientCodecConfigurer.ClientDefaultCodecs { - @Nullable - private DefaultMultipartCodecs multipartCodecs; - @Nullable private Decoder sseDecoder; - @Nullable - private Supplier>> partWritersSupplier; - ClientDefaultCodecsImpl() { } ClientDefaultCodecsImpl(ClientDefaultCodecsImpl other) { super(other); - this.multipartCodecs = (other.multipartCodecs != null ? - new DefaultMultipartCodecs(other.multipartCodecs) : null); this.sseDecoder = other.sseDecoder; } - - /** - * Set a supplier for part writers to use when - * {@link #multipartCodecs()} are not explicitly configured. - * That's the same set of writers as for general except for the multipart - * writer itself. - */ - void setPartWritersSupplier(Supplier>> supplier) { - this.partWritersSupplier = supplier; - initTypedWriters(); - } - - - @Override - public ClientCodecConfigurer.MultipartCodecs multipartCodecs() { - if (this.multipartCodecs == null) { - this.multipartCodecs = new DefaultMultipartCodecs(); - } - return this.multipartCodecs; - } - @Override public void serverSentEventDecoder(Decoder decoder) { this.sseDecoder = decoder; @@ -98,58 +60,4 @@ protected void extendObjectReaders(List> objectReaders) { addCodec(objectReaders, new ServerSentEventHttpMessageReader(decoder)); } - @Override - protected void extendTypedWriters(List> typedWriters) { - addCodec(typedWriters, new MultipartHttpMessageWriter(getPartWriters(), new FormHttpMessageWriter())); - addCodec(typedWriters, new PartEventHttpMessageWriter()); - } - - private List> getPartWriters() { - if (this.multipartCodecs != null) { - return this.multipartCodecs.getWriters(); - } - else if (this.partWritersSupplier != null) { - return this.partWritersSupplier.get(); - } - else { - return Collections.emptyList(); - } - } - - - /** - * Default implementation of {@link ClientCodecConfigurer.MultipartCodecs}. - */ - private class DefaultMultipartCodecs implements ClientCodecConfigurer.MultipartCodecs { - - private final List> writers = new ArrayList<>(); - - - DefaultMultipartCodecs() { - } - - DefaultMultipartCodecs(DefaultMultipartCodecs other) { - this.writers.addAll(other.writers); - } - - - @Override - public ClientCodecConfigurer.MultipartCodecs encoder(Encoder encoder) { - writer(new EncoderHttpMessageWriter<>(encoder)); - initTypedWriters(); - return this; - } - - @Override - public ClientCodecConfigurer.MultipartCodecs writer(HttpMessageWriter writer) { - this.writers.add(writer); - initTypedWriters(); - return this; - } - - List> getWriters() { - return this.writers; - } - } - } diff --git a/spring-web/src/main/java/org/springframework/http/codec/support/DefaultClientCodecConfigurer.java b/spring-web/src/main/java/org/springframework/http/codec/support/DefaultClientCodecConfigurer.java index 382d11bec8c4..fc03ca5de384 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/support/DefaultClientCodecConfigurer.java +++ b/spring-web/src/main/java/org/springframework/http/codec/support/DefaultClientCodecConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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,11 +16,7 @@ package org.springframework.http.codec.support; -import java.util.ArrayList; -import java.util.List; - import org.springframework.http.codec.ClientCodecConfigurer; -import org.springframework.http.codec.HttpMessageWriter; /** * Default implementation of {@link ClientCodecConfigurer}. @@ -33,12 +29,10 @@ public class DefaultClientCodecConfigurer extends BaseCodecConfigurer implements public DefaultClientCodecConfigurer() { super(new ClientDefaultCodecsImpl()); - ((ClientDefaultCodecsImpl) defaultCodecs()).setPartWritersSupplier(this::getPartWriters); } private DefaultClientCodecConfigurer(DefaultClientCodecConfigurer other) { super(other); - ((ClientDefaultCodecsImpl) defaultCodecs()).setPartWritersSupplier(this::getPartWriters); } @@ -57,14 +51,5 @@ protected BaseDefaultCodecs cloneDefaultCodecs() { return new ClientDefaultCodecsImpl((ClientDefaultCodecsImpl) defaultCodecs()); } - private List> getPartWriters() { - List> result = new ArrayList<>(); - result.addAll(this.customCodecs.getTypedWriters().keySet()); - result.addAll(this.defaultCodecs.getBaseTypedWriters()); - result.addAll(this.customCodecs.getObjectWriters().keySet()); - result.addAll(this.defaultCodecs.getBaseObjectWriters()); - result.addAll(this.defaultCodecs.getCatchAllWriters()); - return result; - } } diff --git a/spring-web/src/main/java/org/springframework/http/codec/support/ServerDefaultCodecsImpl.java b/spring-web/src/main/java/org/springframework/http/codec/support/ServerDefaultCodecsImpl.java index 186949655a4f..52c7bf407982 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/support/ServerDefaultCodecsImpl.java +++ b/spring-web/src/main/java/org/springframework/http/codec/support/ServerDefaultCodecsImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -19,14 +19,9 @@ import java.util.List; import org.springframework.core.codec.Encoder; -import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.http.codec.ServerSentEventHttpMessageWriter; -import org.springframework.http.codec.multipart.DefaultPartHttpMessageReader; -import org.springframework.http.codec.multipart.MultipartHttpMessageReader; -import org.springframework.http.codec.multipart.PartEventHttpMessageReader; -import org.springframework.http.codec.multipart.PartHttpMessageWriter; import org.springframework.lang.Nullable; /** @@ -36,9 +31,6 @@ */ class ServerDefaultCodecsImpl extends BaseDefaultCodecs implements ServerCodecConfigurer.ServerDefaultCodecs { - @Nullable - private HttpMessageReader multipartReader; - @Nullable private Encoder sseEncoder; @@ -48,42 +40,16 @@ class ServerDefaultCodecsImpl extends BaseDefaultCodecs implements ServerCodecCo ServerDefaultCodecsImpl(ServerDefaultCodecsImpl other) { super(other); - this.multipartReader = other.multipartReader; this.sseEncoder = other.sseEncoder; } - @Override - public void multipartReader(HttpMessageReader reader) { - this.multipartReader = reader; - initTypedReaders(); - } - @Override public void serverSentEventEncoder(Encoder encoder) { this.sseEncoder = encoder; initObjectWriters(); } - - @Override - protected void extendTypedReaders(List> typedReaders) { - if (this.multipartReader != null) { - addCodec(typedReaders, this.multipartReader); - } - else { - DefaultPartHttpMessageReader partReader = new DefaultPartHttpMessageReader(); - addCodec(typedReaders, partReader); - addCodec(typedReaders, new MultipartHttpMessageReader(partReader)); - } - addCodec(typedReaders, new PartEventHttpMessageReader()); - } - - @Override - protected void extendTypedWriters(List> typedWriters) { - addCodec(typedWriters, new PartHttpMessageWriter()); - } - @Override protected void extendObjectWriters(List> objectWriters) { objectWriters.add(new ServerSentEventHttpMessageWriter(getSseEncoder())); diff --git a/spring-web/src/test/java/org/springframework/http/codec/support/ClientCodecConfigurerTests.java b/spring-web/src/test/java/org/springframework/http/codec/support/ClientCodecConfigurerTests.java index e061ba55f219..aadb220fd0f2 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/support/ClientCodecConfigurerTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/support/ClientCodecConfigurerTests.java @@ -64,8 +64,12 @@ import org.springframework.http.codec.json.Jackson2SmileEncoder; import org.springframework.http.codec.json.KotlinSerializationJsonDecoder; import org.springframework.http.codec.json.KotlinSerializationJsonEncoder; +import org.springframework.http.codec.multipart.DefaultPartHttpMessageReader; +import org.springframework.http.codec.multipart.MultipartHttpMessageReader; import org.springframework.http.codec.multipart.MultipartHttpMessageWriter; +import org.springframework.http.codec.multipart.PartEventHttpMessageReader; import org.springframework.http.codec.multipart.PartEventHttpMessageWriter; +import org.springframework.http.codec.multipart.PartHttpMessageWriter; import org.springframework.http.codec.protobuf.KotlinSerializationProtobufDecoder; import org.springframework.http.codec.protobuf.KotlinSerializationProtobufEncoder; import org.springframework.http.codec.protobuf.ProtobufDecoder; @@ -92,7 +96,7 @@ public class ClientCodecConfigurerTests { @Test public void defaultReaders() { List> readers = this.configurer.getReaders(); - assertThat(readers).hasSize(17); + assertThat(readers).hasSize(20); assertThat(getNextDecoder(readers).getClass()).isEqualTo(ByteArrayDecoder.class); assertThat(getNextDecoder(readers).getClass()).isEqualTo(ByteBufferDecoder.class); assertThat(getNextDecoder(readers).getClass()).isEqualTo(DataBufferDecoder.class); @@ -103,6 +107,9 @@ public void defaultReaders() { assertThat(getNextDecoder(readers).getClass()).isEqualTo(ProtobufDecoder.class); // SPR-16804 assertThat(readers.get(this.index.getAndIncrement()).getClass()).isEqualTo(FormHttpMessageReader.class); + assertThat(readers.get(this.index.getAndIncrement()).getClass()).isEqualTo(DefaultPartHttpMessageReader.class); + assertThat(readers.get(this.index.getAndIncrement()).getClass()).isEqualTo(MultipartHttpMessageReader.class); + assertThat(readers.get(this.index.getAndIncrement()).getClass()).isEqualTo(PartEventHttpMessageReader.class); assertThat(getNextDecoder(readers).getClass()).isEqualTo(KotlinSerializationCborDecoder.class); assertThat(getNextDecoder(readers).getClass()).isEqualTo(KotlinSerializationJsonDecoder.class); assertThat(getNextDecoder(readers).getClass()).isEqualTo(KotlinSerializationProtobufDecoder.class); @@ -116,7 +123,7 @@ public void defaultReaders() { @Test public void defaultWriters() { List> writers = this.configurer.getWriters(); - assertThat(writers).hasSize(17); + assertThat(writers).hasSize(18); assertThat(getNextEncoder(writers).getClass()).isEqualTo(ByteArrayEncoder.class); assertThat(getNextEncoder(writers).getClass()).isEqualTo(ByteBufferEncoder.class); assertThat(getNextEncoder(writers).getClass()).isEqualTo(DataBufferEncoder.class); @@ -127,6 +134,7 @@ public void defaultWriters() { assertThat(writers.get(index.getAndIncrement()).getClass()).isEqualTo(ProtobufHttpMessageWriter.class); assertThat(writers.get(this.index.getAndIncrement()).getClass()).isEqualTo(MultipartHttpMessageWriter.class); assertThat(writers.get(this.index.getAndIncrement()).getClass()).isEqualTo(PartEventHttpMessageWriter.class); + assertThat(writers.get(this.index.getAndIncrement()).getClass()).isEqualTo(PartHttpMessageWriter.class); assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationCborEncoder.class); assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationJsonEncoder.class); assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationProtobufEncoder.class); @@ -184,7 +192,7 @@ public void maxInMemorySize() { int size = 99; this.configurer.defaultCodecs().maxInMemorySize(size); List> readers = this.configurer.getReaders(); - assertThat(readers).hasSize(17); + assertThat(readers).hasSize(20); assertThat(((ByteArrayDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size); assertThat(((ByteBufferDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size); assertThat(((DataBufferDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size); @@ -194,7 +202,9 @@ public void maxInMemorySize() { assertThat(((StringDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size); assertThat(((ProtobufDecoder) getNextDecoder(readers)).getMaxMessageSize()).isEqualTo(size); assertThat(((FormHttpMessageReader) nextReader(readers)).getMaxInMemorySize()).isEqualTo(size); - + assertThat(((DefaultPartHttpMessageReader) nextReader(readers)).getMaxInMemorySize()).isEqualTo(size); + nextReader(readers); + assertThat(((PartEventHttpMessageReader) nextReader(readers)).getMaxInMemorySize()).isEqualTo(size); assertThat(((KotlinSerializationCborDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size); assertThat(((KotlinSerializationJsonDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size); assertThat(((KotlinSerializationProtobufDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size); @@ -245,7 +255,7 @@ public void clonedConfigurer() { writers = findCodec(this.configurer.getWriters(), MultipartHttpMessageWriter.class).getPartWriters(); assertThat(sseDecoder).isNotSameAs(jackson2Decoder); - assertThat(writers).hasSize(15); + assertThat(writers).hasSize(18); } @Test // gh-24194 @@ -255,7 +265,7 @@ public void cloneShouldNotDropMultipartCodecs() { List> writers = findCodec(clone.getWriters(), MultipartHttpMessageWriter.class).getPartWriters(); - assertThat(writers).hasSize(15); + assertThat(writers).hasSize(18); } @Test @@ -269,7 +279,7 @@ public void cloneShouldNotBeImpactedByChangesToOriginal() { List> writers = findCodec(clone.getWriters(), MultipartHttpMessageWriter.class).getPartWriters(); - assertThat(writers).hasSize(15); + assertThat(writers).hasSize(18); } private Decoder getNextDecoder(List> readers) { diff --git a/spring-web/src/test/java/org/springframework/http/codec/support/CodecConfigurerTests.java b/spring-web/src/test/java/org/springframework/http/codec/support/CodecConfigurerTests.java index fc3358514f1a..40b554afd1cd 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/support/CodecConfigurerTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/support/CodecConfigurerTests.java @@ -58,6 +58,12 @@ import org.springframework.http.codec.json.Jackson2SmileEncoder; import org.springframework.http.codec.json.KotlinSerializationJsonDecoder; import org.springframework.http.codec.json.KotlinSerializationJsonEncoder; +import org.springframework.http.codec.multipart.DefaultPartHttpMessageReader; +import org.springframework.http.codec.multipart.MultipartHttpMessageReader; +import org.springframework.http.codec.multipart.MultipartHttpMessageWriter; +import org.springframework.http.codec.multipart.PartEventHttpMessageReader; +import org.springframework.http.codec.multipart.PartEventHttpMessageWriter; +import org.springframework.http.codec.multipart.PartHttpMessageWriter; import org.springframework.http.codec.protobuf.KotlinSerializationProtobufDecoder; import org.springframework.http.codec.protobuf.KotlinSerializationProtobufEncoder; import org.springframework.http.codec.protobuf.ProtobufDecoder; @@ -87,7 +93,7 @@ class CodecConfigurerTests { @Test void defaultReaders() { List> readers = this.configurer.getReaders(); - assertThat(readers).hasSize(16); + assertThat(readers).hasSize(19); assertThat(getNextDecoder(readers).getClass()).isEqualTo(ByteArrayDecoder.class); assertThat(getNextDecoder(readers).getClass()).isEqualTo(ByteBufferDecoder.class); assertThat(getNextDecoder(readers).getClass()).isEqualTo(DataBufferDecoder.class); @@ -97,6 +103,9 @@ void defaultReaders() { assertStringDecoder(getNextDecoder(readers), true); assertThat(getNextDecoder(readers).getClass()).isEqualTo(ProtobufDecoder.class); assertThat(readers.get(this.index.getAndIncrement()).getClass()).isEqualTo(FormHttpMessageReader.class); + assertThat(readers.get(this.index.getAndIncrement()).getClass()).isEqualTo(DefaultPartHttpMessageReader.class); + assertThat(readers.get(this.index.getAndIncrement()).getClass()).isEqualTo(MultipartHttpMessageReader.class); + assertThat(readers.get(this.index.getAndIncrement()).getClass()).isEqualTo(PartEventHttpMessageReader.class); assertThat(getNextDecoder(readers).getClass()).isEqualTo(KotlinSerializationCborDecoder.class); assertThat(getNextDecoder(readers).getClass()).isEqualTo(KotlinSerializationJsonDecoder.class); assertThat(getNextDecoder(readers).getClass()).isEqualTo(KotlinSerializationProtobufDecoder.class); @@ -109,7 +118,7 @@ void defaultReaders() { @Test void defaultWriters() { List> writers = this.configurer.getWriters(); - assertThat(writers).hasSize(15); + assertThat(writers).hasSize(18); assertThat(getNextEncoder(writers).getClass()).isEqualTo(ByteArrayEncoder.class); assertThat(getNextEncoder(writers).getClass()).isEqualTo(ByteBufferEncoder.class); assertThat(getNextEncoder(writers).getClass()).isEqualTo(DataBufferEncoder.class); @@ -118,6 +127,9 @@ void defaultWriters() { assertThat(writers.get(index.getAndIncrement()).getClass()).isEqualTo(ResourceHttpMessageWriter.class); assertStringEncoder(getNextEncoder(writers), true); assertThat(writers.get(index.getAndIncrement()).getClass()).isEqualTo(ProtobufHttpMessageWriter.class); + assertThat(writers.get(index.getAndIncrement()).getClass()).isEqualTo(MultipartHttpMessageWriter.class); + assertThat(writers.get(index.getAndIncrement()).getClass()).isEqualTo(PartEventHttpMessageWriter.class); + assertThat(writers.get(index.getAndIncrement()).getClass()).isEqualTo(PartHttpMessageWriter.class); assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationCborEncoder.class); assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationJsonEncoder.class); assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationProtobufEncoder.class); @@ -149,7 +161,7 @@ void defaultAndCustomReaders() { List> readers = this.configurer.getReaders(); - assertThat(readers).hasSize(20); + assertThat(readers).hasSize(23); assertThat(getNextDecoder(readers)).isSameAs(customDecoder1); assertThat(readers.get(this.index.getAndIncrement())).isSameAs(customReader1); assertThat(getNextDecoder(readers).getClass()).isEqualTo(ByteArrayDecoder.class); @@ -161,6 +173,9 @@ void defaultAndCustomReaders() { assertThat(getNextDecoder(readers).getClass()).isEqualTo(StringDecoder.class); assertThat(getNextDecoder(readers).getClass()).isEqualTo(ProtobufDecoder.class); assertThat(readers.get(this.index.getAndIncrement()).getClass()).isEqualTo(FormHttpMessageReader.class); + assertThat(readers.get(this.index.getAndIncrement()).getClass()).isEqualTo(DefaultPartHttpMessageReader.class); + assertThat(readers.get(this.index.getAndIncrement()).getClass()).isEqualTo(MultipartHttpMessageReader.class); + assertThat(readers.get(this.index.getAndIncrement()).getClass()).isEqualTo(PartEventHttpMessageReader.class); assertThat(getNextDecoder(readers)).isSameAs(customDecoder2); assertThat(readers.get(this.index.getAndIncrement())).isSameAs(customReader2); assertThat(getNextDecoder(readers).getClass()).isEqualTo(KotlinSerializationCborDecoder.class); @@ -194,7 +209,7 @@ void defaultAndCustomWriters() { List> writers = this.configurer.getWriters(); - assertThat(writers).hasSize(19); + assertThat(writers).hasSize(22); assertThat(getNextEncoder(writers)).isSameAs(customEncoder1); assertThat(writers.get(this.index.getAndIncrement())).isSameAs(customWriter1); assertThat(getNextEncoder(writers).getClass()).isEqualTo(ByteArrayEncoder.class); @@ -205,6 +220,9 @@ void defaultAndCustomWriters() { assertThat(writers.get(index.getAndIncrement()).getClass()).isEqualTo(ResourceHttpMessageWriter.class); assertThat(getNextEncoder(writers).getClass()).isEqualTo(CharSequenceEncoder.class); assertThat(writers.get(index.getAndIncrement()).getClass()).isEqualTo(ProtobufHttpMessageWriter.class); + assertThat(writers.get(index.getAndIncrement()).getClass()).isEqualTo(MultipartHttpMessageWriter.class); + assertThat(writers.get(index.getAndIncrement()).getClass()).isEqualTo(PartEventHttpMessageWriter.class); + assertThat(writers.get(index.getAndIncrement()).getClass()).isEqualTo(PartHttpMessageWriter.class); assertThat(getNextEncoder(writers)).isSameAs(customEncoder2); assertThat(writers.get(this.index.getAndIncrement())).isSameAs(customWriter2); assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationCborEncoder.class); diff --git a/spring-web/src/test/java/org/springframework/http/codec/support/ServerCodecConfigurerTests.java b/spring-web/src/test/java/org/springframework/http/codec/support/ServerCodecConfigurerTests.java index a7c84bf1382c..571001beb6ef 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/support/ServerCodecConfigurerTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/support/ServerCodecConfigurerTests.java @@ -64,7 +64,9 @@ import org.springframework.http.codec.json.KotlinSerializationJsonEncoder; import org.springframework.http.codec.multipart.DefaultPartHttpMessageReader; import org.springframework.http.codec.multipart.MultipartHttpMessageReader; +import org.springframework.http.codec.multipart.MultipartHttpMessageWriter; import org.springframework.http.codec.multipart.PartEventHttpMessageReader; +import org.springframework.http.codec.multipart.PartEventHttpMessageWriter; import org.springframework.http.codec.multipart.PartHttpMessageWriter; import org.springframework.http.codec.protobuf.KotlinSerializationProtobufDecoder; import org.springframework.http.codec.protobuf.KotlinSerializationProtobufEncoder; @@ -117,7 +119,7 @@ public void defaultReaders() { @Test public void defaultWriters() { List> writers = this.configurer.getWriters(); - assertThat(writers).hasSize(17); + assertThat(writers).hasSize(19); assertThat(getNextEncoder(writers).getClass()).isEqualTo(ByteArrayEncoder.class); assertThat(getNextEncoder(writers).getClass()).isEqualTo(ByteBufferEncoder.class); assertThat(getNextEncoder(writers).getClass()).isEqualTo(DataBufferEncoder.class); @@ -126,6 +128,8 @@ public void defaultWriters() { assertThat(writers.get(index.getAndIncrement()).getClass()).isEqualTo(ResourceHttpMessageWriter.class); assertStringEncoder(getNextEncoder(writers), true); assertThat(writers.get(index.getAndIncrement()).getClass()).isEqualTo(ProtobufHttpMessageWriter.class); + assertThat(writers.get(this.index.getAndIncrement()).getClass()).isEqualTo(MultipartHttpMessageWriter.class); + assertThat(writers.get(this.index.getAndIncrement()).getClass()).isEqualTo(PartEventHttpMessageWriter.class); assertThat(writers.get(this.index.getAndIncrement()).getClass()).isEqualTo(PartHttpMessageWriter.class); assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationCborEncoder.class); assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationJsonEncoder.class); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java index fed7c90ee046..922ce42a1423 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/config/WebFluxConfigurationSupportTests.java @@ -200,7 +200,7 @@ public void responseEntityResultHandler() { assertThat(handler.getOrder()).isEqualTo(0); List> writers = handler.getMessageWriters(); - assertThat(writers).hasSize(14); + assertThat(writers).hasSize(16); assertHasMessageWriter(writers, forClass(byte[].class), APPLICATION_OCTET_STREAM); assertHasMessageWriter(writers, forClass(ByteBuffer.class), APPLICATION_OCTET_STREAM); @@ -228,7 +228,7 @@ public void responseBodyResultHandler() { assertThat(handler.getOrder()).isEqualTo(100); List> writers = handler.getMessageWriters(); - assertThat(writers).hasSize(14); + assertThat(writers).hasSize(16); assertHasMessageWriter(writers, forClass(byte[].class), APPLICATION_OCTET_STREAM); assertHasMessageWriter(writers, forClass(ByteBuffer.class), APPLICATION_OCTET_STREAM);