001/*
002 * Copyright 2002-2020 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.http.codec;
018
019import java.util.List;
020import java.util.function.Consumer;
021
022import org.springframework.core.codec.Decoder;
023import org.springframework.core.codec.Encoder;
024import org.springframework.lang.Nullable;
025
026/**
027 * Defines a common interface for configuring either client or server HTTP
028 * message readers and writers. This is used as follows:
029 * <ul>
030 * <li>Use {@link ClientCodecConfigurer#create()} or
031 * {@link ServerCodecConfigurer#create()} to create an instance.
032 * <li>Use {@link #defaultCodecs()} to customize HTTP message readers or writers
033 * registered by default.
034 * <li>Use {@link #customCodecs()} to add custom HTTP message readers or writers.
035 * <li>Use {@link #getReaders()} and {@link #getWriters()} to obtain the list of
036 * configured HTTP message readers and writers.
037 * </ul>
038 *
039 * <p>HTTP message readers and writers are divided into 3 categories that are
040 * ordered as follows:
041 * <ol>
042 * <li>Typed readers and writers that support specific types, e.g. byte[], String.
043 * <li>Object readers and writers, e.g. JSON, XML.
044 * <li>Catch-all readers or writers, e.g. String with any media type.
045 * </ol>
046 *
047 * <p>Typed and object readers are further sub-divided and ordered as follows:
048 * <ol>
049 * <li>Default HTTP reader and writer registrations.
050 * <li>Custom readers and writers.
051 * </ol>
052 *
053 * @author Rossen Stoyanchev
054 * @since 5.0
055 */
056public interface CodecConfigurer {
057
058        /**
059         * Provides a way to customize or replace HTTP message readers and writers
060         * registered by default.
061         * @see #registerDefaults(boolean)
062         */
063        DefaultCodecs defaultCodecs();
064
065        /**
066         * Register custom HTTP message readers or writers in addition to the ones
067         * registered by default.
068         */
069        CustomCodecs customCodecs();
070
071        /**
072         * Provides a way to completely turn off registration of default HTTP message
073         * readers and writers, and instead rely only on the ones provided via
074         * {@link #customCodecs()}.
075         * <p>By default this is set to {@code "true"} in which case default
076         * registrations are made; setting this to {@code false} disables default
077         * registrations.
078         */
079        void registerDefaults(boolean registerDefaults);
080
081
082        /**
083         * Obtain the configured HTTP message readers.
084         */
085        List<HttpMessageReader<?>> getReaders();
086
087        /**
088         * Obtain the configured HTTP message writers.
089         */
090        List<HttpMessageWriter<?>> getWriters();
091
092        /**
093         * Create a copy of this {@link CodecConfigurer}. The returned clone has its
094         * own lists of default and custom codecs and generally can be configured
095         * independently. Keep in mind however that codec instances (if any are
096         * configured) are themselves not cloned.
097         * @since 5.1.12
098         */
099        CodecConfigurer clone();
100
101
102        /**
103         * Customize or replace the HTTP message readers and writers registered by
104         * default. The options are further extended by
105         * {@link ClientCodecConfigurer.ClientDefaultCodecs ClientDefaultCodecs} and
106         * {@link ServerCodecConfigurer.ServerDefaultCodecs ServerDefaultCodecs}.
107         */
108        interface DefaultCodecs {
109
110                /**
111                 * Override the default Jackson JSON {@code Decoder}.
112                 * <p>Note that {@link #maxInMemorySize(int)}, if configured, will be
113                 * applied to the given decoder.
114                 * @param decoder the decoder instance to use
115                 * @see org.springframework.http.codec.json.Jackson2JsonDecoder
116                 */
117                void jackson2JsonDecoder(Decoder<?> decoder);
118
119                /**
120                 * Override the default Jackson JSON {@code Encoder}.
121                 * @param encoder the encoder instance to use
122                 * @see org.springframework.http.codec.json.Jackson2JsonEncoder
123                 */
124                void jackson2JsonEncoder(Encoder<?> encoder);
125
126                /**
127                 * Override the default Jackson Smile {@code Decoder}.
128                 * <p>Note that {@link #maxInMemorySize(int)}, if configured, will be
129                 * applied to the given decoder.
130                 * @param decoder the decoder instance to use
131                 * @see org.springframework.http.codec.json.Jackson2SmileDecoder
132                 */
133                void jackson2SmileDecoder(Decoder<?> decoder);
134
135                /**
136                 * Override the default Jackson Smile {@code Encoder}.
137                 * @param encoder the encoder instance to use
138                 * @see org.springframework.http.codec.json.Jackson2SmileEncoder
139                 */
140                void jackson2SmileEncoder(Encoder<?> encoder);
141
142                /**
143                 * Override the default Protobuf {@code Decoder}.
144                 * <p>Note that {@link #maxInMemorySize(int)}, if configured, will be
145                 * applied to the given decoder.
146                 * @param decoder the decoder instance to use
147                 * @since 5.1
148                 * @see org.springframework.http.codec.protobuf.ProtobufDecoder
149                 */
150                void protobufDecoder(Decoder<?> decoder);
151
152                /**
153                 * Override the default Protobuf {@code Encoder}.
154                 * @param encoder the encoder instance to use
155                 * @since 5.1
156                 * @see org.springframework.http.codec.protobuf.ProtobufEncoder
157                 * @see org.springframework.http.codec.protobuf.ProtobufHttpMessageWriter
158                 */
159                void protobufEncoder(Encoder<?> encoder);
160
161                /**
162                 * Override the default JAXB2 {@code Decoder}.
163                 * <p>Note that {@link #maxInMemorySize(int)}, if configured, will be
164                 * applied to the given decoder.
165                 * @param decoder the decoder instance to use
166                 * @since 5.1.3
167                 * @see org.springframework.http.codec.xml.Jaxb2XmlDecoder
168                 */
169                void jaxb2Decoder(Decoder<?> decoder);
170
171                /**
172                 * Override the default JABX2 {@code Encoder}.
173                 * @param encoder the encoder instance to use
174                 * @since 5.1.3
175                 * @see org.springframework.http.codec.xml.Jaxb2XmlEncoder
176                 */
177                void jaxb2Encoder(Encoder<?> encoder);
178
179                /**
180                 * Configure a limit on the number of bytes that can be buffered whenever
181                 * the input stream needs to be aggregated. This can be a result of
182                 * decoding to a single {@code DataBuffer},
183                 * {@link java.nio.ByteBuffer ByteBuffer}, {@code byte[]},
184                 * {@link org.springframework.core.io.Resource Resource}, {@code String}, etc.
185                 * It can also occur when splitting the input stream, e.g. delimited text,
186                 * in which case the limit applies to data buffered between delimiters.
187                 * <p>By default this is not set, in which case individual codec defaults
188                 * apply. All codecs are limited to 256K by default.
189                 * @param byteCount the max number of bytes to buffer, or -1 for unlimited
190                 * @since 5.1.11
191                 */
192                void maxInMemorySize(int byteCount);
193
194                /**
195                 * Whether to log form data at DEBUG level, and headers at TRACE level.
196                 * Both may contain sensitive information.
197                 * <p>By default set to {@code false} so that request details are not shown.
198                 * @param enable whether to enable or not
199                 * @since 5.1
200                 */
201                void enableLoggingRequestDetails(boolean enable);
202        }
203
204
205        /**
206         * Registry for custom HTTP message readers and writers.
207         */
208        interface CustomCodecs {
209
210                /**
211                 * Register a custom codec. This is expected to be one of the following:
212                 * <ul>
213                 * <li>{@link HttpMessageReader}
214                 * <li>{@link HttpMessageWriter}
215                 * <li>{@link Encoder} (wrapped internally with {@link EncoderHttpMessageWriter})
216                 * <li>{@link Decoder} (wrapped internally with {@link DecoderHttpMessageReader})
217                 * </ul>
218                 * @param codec the codec to register
219                 * @since 5.1.13
220                 */
221                void register(Object codec);
222
223                /**
224                 * Variant of {@link #register(Object)} that also applies the below
225                 * properties, if configured, via {@link #defaultCodecs()}:
226                 * <ul>
227                 * <li>{@link CodecConfigurer.DefaultCodecs#maxInMemorySize(int) maxInMemorySize}
228                 * <li>{@link CodecConfigurer.DefaultCodecs#enableLoggingRequestDetails(boolean) enableLoggingRequestDetails}
229                 * </ul>
230                 * <p>The properties are applied every time {@link #getReaders()} or
231                 * {@link #getWriters()} are used to obtain the list of configured
232                 * readers or writers.
233                 * @param codec the codec to register and apply default config to
234                 * @since 5.1.13
235                 */
236                void registerWithDefaultConfig(Object codec);
237
238                /**
239                 * Variant of {@link #register(Object)} that also allows the caller to
240                 * apply the properties from {@link DefaultCodecConfig} to the given
241                 * codec. If you want to apply all the properties, prefer using
242                 * {@link #registerWithDefaultConfig(Object)}.
243                 * <p>The consumer is called every time {@link #getReaders()} or
244                 * {@link #getWriters()} are used to obtain the list of configured
245                 * readers or writers.
246                 * @param codec the codec to register
247                 * @param configConsumer consumer of the default config
248                 * @since 5.1.13
249                 */
250                void registerWithDefaultConfig(Object codec, Consumer<DefaultCodecConfig> configConsumer);
251
252                /**
253                 * Add a custom {@code Decoder} internally wrapped with
254                 * {@link DecoderHttpMessageReader}).
255                 * @param decoder the decoder to add
256                 * @deprecated as of 5.1.13, use {@link #register(Object)} or
257                 * {@link #registerWithDefaultConfig(Object)} instead.
258                 */
259                @Deprecated
260                void decoder(Decoder<?> decoder);
261
262                /**
263                 * Add a custom {@code Encoder}, internally wrapped with
264                 * {@link EncoderHttpMessageWriter}.
265                 * @param encoder the encoder to add
266                 * @deprecated as of 5.1.13, use {@link #register(Object)} or
267                 * {@link #registerWithDefaultConfig(Object)} instead.
268                 */
269                @Deprecated
270                void encoder(Encoder<?> encoder);
271
272                /**
273                 * Add a custom {@link HttpMessageReader}. For readers of type
274                 * {@link DecoderHttpMessageReader} consider using the shortcut
275                 * {@link #decoder(Decoder)} instead.
276                 * @param reader the reader to add
277                 * @deprecated as of 5.1.13, use {@link #register(Object)} or
278                 * {@link #registerWithDefaultConfig(Object)} instead.
279                 */
280                @Deprecated
281                void reader(HttpMessageReader<?> reader);
282
283                /**
284                 * Add a custom {@link HttpMessageWriter}. For writers of type
285                 * {@link EncoderHttpMessageWriter} consider using the shortcut
286                 * {@link #encoder(Encoder)} instead.
287                 * @param writer the writer to add
288                 * @deprecated as of 5.1.13, use {@link #register(Object)} or
289                 * {@link #registerWithDefaultConfig(Object)} instead.
290                 */
291                @Deprecated
292                void writer(HttpMessageWriter<?> writer);
293
294                /**
295                 * Register a callback for the {@link DefaultCodecConfig configuration}
296                 * applied to default codecs. This allows custom codecs to follow general
297                 * guidelines applied to default ones, such as logging details and limiting
298                 * the amount of buffered data.
299                 * @param codecsConfigConsumer the default codecs configuration callback
300                 * @deprecated as of 5.1.13, use {@link #registerWithDefaultConfig(Object)}
301                 * or {@link #registerWithDefaultConfig(Object, Consumer)} instead.
302                 */
303                @Deprecated
304                void withDefaultCodecConfig(Consumer<DefaultCodecConfig> codecsConfigConsumer);
305        }
306
307
308        /**
309         * Exposes the values of properties configured through
310         * {@link #defaultCodecs()} that are applied to default codecs.
311         * The main purpose of this interface is to provide access to them so they
312         * can also be applied to custom codecs if needed.
313         * @since 5.1.12
314         * @see CustomCodecs#registerWithDefaultConfig(Object, Consumer)
315         */
316        interface DefaultCodecConfig {
317
318                /**
319                 * Get the configured limit on the number of bytes that can be buffered whenever
320                 * the input stream needs to be aggregated.
321                 */
322                @Nullable
323                Integer maxInMemorySize();
324
325                /**
326                 * Whether to log form data at DEBUG level, and headers at TRACE level.
327                 * Both may contain sensitive information.
328                 */
329                @Nullable
330                Boolean isEnableLoggingRequestDetails();
331        }
332
333}