Align multipart codecs on client and server
This commit ensures that the same multipart codecs are registered on both client and server. Previously, only the client enabled only sending multipart, and the server only receiving. Closes gh-29630
This commit is contained in:
parent
46fc28fd1a
commit
c79ae0c842
|
@ -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 @@ public interface ClientCodecConfigurer extends CodecConfigurer {
|
|||
*/
|
||||
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.
|
||||
* <p>By default if this is not set, and Jackson is available, the
|
||||
|
@ -102,26 +94,4 @@ public interface ClientCodecConfigurer extends CodecConfigurer {
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -258,6 +258,24 @@ public interface CodecConfigurer {
|
|||
* @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.
|
||||
* <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.
|
||||
* @since 6.0.3
|
||||
*/
|
||||
void multipartReader(HttpMessageReader<?> reader);
|
||||
}
|
||||
|
||||
|
||||
|
@ -389,4 +407,27 @@ public interface CodecConfigurer {
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 @@ public interface ServerCodecConfigurer extends CodecConfigurer {
|
|||
*/
|
||||
interface ServerDefaultCodecs extends DefaultCodecs {
|
||||
|
||||
/**
|
||||
* Configure the {@code HttpMessageReader} to use for multipart requests.
|
||||
* <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.
|
||||
* @since 5.1.11
|
||||
*/
|
||||
void multipartReader(HttpMessageReader<?> reader);
|
||||
|
||||
/**
|
||||
* Configure the {@code Encoder} to use for Server-Sent Events.
|
||||
* <p>By default if this is not set, and Jackson is available, the
|
||||
|
|
|
@ -79,7 +79,7 @@ public class MultipartHttpMessageWriter extends MultipartWriterSupport
|
|||
private static final Map<String, Object> DEFAULT_HINTS = Hints.from(Hints.SUPPRESS_LOGGING_HINT, true);
|
||||
|
||||
|
||||
private final List<HttpMessageWriter<?>> partWriters;
|
||||
private final Supplier<List<HttpMessageWriter<?>>> partWritersSupplier;
|
||||
|
||||
@Nullable
|
||||
private final HttpMessageWriter<MultiValueMap<String, String>> formWriter;
|
||||
|
@ -112,8 +112,23 @@ public class MultipartHttpMessageWriter extends MultipartWriterSupport
|
|||
public MultipartHttpMessageWriter(List<HttpMessageWriter<?>> partWriters,
|
||||
@Nullable HttpMessageWriter<MultiValueMap<String, String>> 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<List<HttpMessageWriter<?>>> partWritersSupplier,
|
||||
@Nullable HttpMessageWriter<MultiValueMap<String, String>> formWriter) {
|
||||
|
||||
super(initMediaTypes(formWriter));
|
||||
this.partWriters = partWriters;
|
||||
this.partWritersSupplier = partWritersSupplier;
|
||||
this.formWriter = formWriter;
|
||||
}
|
||||
|
||||
|
@ -131,7 +146,7 @@ public class MultipartHttpMessageWriter extends MultipartWriterSupport
|
|||
* @since 5.0.7
|
||||
*/
|
||||
public List<HttpMessageWriter<?>> getPartWriters() {
|
||||
return Collections.unmodifiableList(this.partWriters);
|
||||
return Collections.unmodifiableList(this.partWritersSupplier.get());
|
||||
}
|
||||
|
||||
|
||||
|
@ -264,8 +279,8 @@ public class MultipartHttpMessageWriter extends MultipartWriterSupport
|
|||
|
||||
MediaType contentType = headers.getContentType();
|
||||
|
||||
final ResolvableType finalBodyType = resolvableType;
|
||||
Optional<HttpMessageWriter<?>> writer = this.partWriters.stream()
|
||||
ResolvableType finalBodyType = resolvableType;
|
||||
Optional<HttpMessageWriter<?>> writer = this.partWritersSupplier.get().stream()
|
||||
.filter(partWriter -> partWriter.canWrite(finalBodyType, contentType))
|
||||
.findFirst();
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.util.Collections;
|
|||
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.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;
|
||||
|
@ -160,6 +163,15 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
|
|||
@Nullable
|
||||
private Encoder<?> kotlinSerializationProtobufEncoder;
|
||||
|
||||
@Nullable
|
||||
private DefaultMultipartCodecs multipartCodecs;
|
||||
|
||||
@Nullable
|
||||
private Supplier<List<HttpMessageWriter<?>>> partWritersSupplier;
|
||||
|
||||
@Nullable
|
||||
private HttpMessageReader<?> multipartReader;
|
||||
|
||||
@Nullable
|
||||
private Consumer<Object> codecConsumer;
|
||||
|
||||
|
@ -224,6 +236,9 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
|
|||
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 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
|
|||
}
|
||||
}
|
||||
|
||||
@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<List<HttpMessageWriter<?>>> supplier) {
|
||||
this.partWritersSupplier = supplier;
|
||||
initTypedWriters();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Boolean isEnableLoggingRequestDetails() {
|
||||
|
@ -405,6 +445,15 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
|
|||
(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 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
|
|||
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<HttpMessageWriter<?>> 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 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
|
|||
return this.kotlinSerializationJsonEncoder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default implementation of {@link CodecConfigurer.MultipartCodecs}.
|
||||
*/
|
||||
protected class DefaultMultipartCodecs implements CodecConfigurer.MultipartCodecs {
|
||||
|
||||
private final List<HttpMessageWriter<?>> 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<HttpMessageWriter<?>> getWriters() {
|
||||
return this.writers;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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 @@ import org.springframework.lang.Nullable;
|
|||
*/
|
||||
class ClientDefaultCodecsImpl extends BaseDefaultCodecs implements ClientCodecConfigurer.ClientDefaultCodecs {
|
||||
|
||||
@Nullable
|
||||
private DefaultMultipartCodecs multipartCodecs;
|
||||
|
||||
@Nullable
|
||||
private Decoder<?> sseDecoder;
|
||||
|
||||
@Nullable
|
||||
private Supplier<List<HttpMessageWriter<?>>> 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<List<HttpMessageWriter<?>>> 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 @@ class ClientDefaultCodecsImpl extends BaseDefaultCodecs implements ClientCodecCo
|
|||
addCodec(objectReaders, new ServerSentEventHttpMessageReader(decoder));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void extendTypedWriters(List<HttpMessageWriter<?>> typedWriters) {
|
||||
addCodec(typedWriters, new MultipartHttpMessageWriter(getPartWriters(), new FormHttpMessageWriter()));
|
||||
addCodec(typedWriters, new PartEventHttpMessageWriter());
|
||||
}
|
||||
|
||||
private List<HttpMessageWriter<?>> 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<HttpMessageWriter<?>> 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<HttpMessageWriter<?>> getWriters() {
|
||||
return this.writers;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 @@ public class DefaultClientCodecConfigurer extends BaseCodecConfigurer implements
|
|||
return new ClientDefaultCodecsImpl((ClientDefaultCodecsImpl) defaultCodecs());
|
||||
}
|
||||
|
||||
private List<HttpMessageWriter<?>> getPartWriters() {
|
||||
List<HttpMessageWriter<?>> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 @@ package org.springframework.http.codec.support;
|
|||
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 @@ import org.springframework.lang.Nullable;
|
|||
*/
|
||||
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<HttpMessageReader<?>> 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<HttpMessageWriter<?>> typedWriters) {
|
||||
addCodec(typedWriters, new PartHttpMessageWriter());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void extendObjectWriters(List<HttpMessageWriter<?>> objectWriters) {
|
||||
objectWriters.add(new ServerSentEventHttpMessageWriter(getSseEncoder()));
|
||||
|
|
|
@ -64,8 +64,12 @@ import org.springframework.http.codec.json.Jackson2SmileDecoder;
|
|||
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<HttpMessageReader<?>> 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 class ClientCodecConfigurerTests {
|
|||
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 class ClientCodecConfigurerTests {
|
|||
@Test
|
||||
public void defaultWriters() {
|
||||
List<HttpMessageWriter<?>> 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 class ClientCodecConfigurerTests {
|
|||
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 class ClientCodecConfigurerTests {
|
|||
int size = 99;
|
||||
this.configurer.defaultCodecs().maxInMemorySize(size);
|
||||
List<HttpMessageReader<?>> 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 class ClientCodecConfigurerTests {
|
|||
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 class ClientCodecConfigurerTests {
|
|||
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 class ClientCodecConfigurerTests {
|
|||
List<HttpMessageWriter<?>> writers =
|
||||
findCodec(clone.getWriters(), MultipartHttpMessageWriter.class).getPartWriters();
|
||||
|
||||
assertThat(writers).hasSize(15);
|
||||
assertThat(writers).hasSize(18);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -269,7 +279,7 @@ public class ClientCodecConfigurerTests {
|
|||
List<HttpMessageWriter<?>> writers =
|
||||
findCodec(clone.getWriters(), MultipartHttpMessageWriter.class).getPartWriters();
|
||||
|
||||
assertThat(writers).hasSize(15);
|
||||
assertThat(writers).hasSize(18);
|
||||
}
|
||||
|
||||
private Decoder<?> getNextDecoder(List<HttpMessageReader<?>> readers) {
|
||||
|
|
|
@ -58,6 +58,12 @@ import org.springframework.http.codec.json.Jackson2SmileDecoder;
|
|||
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<HttpMessageReader<?>> 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 @@ class CodecConfigurerTests {
|
|||
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 @@ class CodecConfigurerTests {
|
|||
@Test
|
||||
void defaultWriters() {
|
||||
List<HttpMessageWriter<?>> 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 @@ class CodecConfigurerTests {
|
|||
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 @@ class CodecConfigurerTests {
|
|||
|
||||
List<HttpMessageReader<?>> 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 @@ class CodecConfigurerTests {
|
|||
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 @@ class CodecConfigurerTests {
|
|||
|
||||
List<HttpMessageWriter<?>> 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 @@ class CodecConfigurerTests {
|
|||
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);
|
||||
|
|
|
@ -64,7 +64,9 @@ 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;
|
||||
|
@ -117,7 +119,7 @@ public class ServerCodecConfigurerTests {
|
|||
@Test
|
||||
public void defaultWriters() {
|
||||
List<HttpMessageWriter<?>> 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 class ServerCodecConfigurerTests {
|
|||
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);
|
||||
|
|
|
@ -200,7 +200,7 @@ public class WebFluxConfigurationSupportTests {
|
|||
assertThat(handler.getOrder()).isEqualTo(0);
|
||||
|
||||
List<HttpMessageWriter<?>> 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 class WebFluxConfigurationSupportTests {
|
|||
assertThat(handler.getOrder()).isEqualTo(100);
|
||||
|
||||
List<HttpMessageWriter<?>> 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);
|
||||
|
|
Loading…
Reference in New Issue