Enhancements to content-type negotiation
- Added logic to wrap custom (user) message converters with NegotiatingMessageConverterWrapper - Removed 'addDefaultConverters' flag from ContextFunctionCatalogAutoConfiguration as it is more confusing then useful - Added test which uses wild card accept content-type with several converters available to ensure the appropriate one is used - Made NegotiatingMessageConverterWrapper package private and moved it and it's test to a contex.config package Resolves #462
This commit is contained in:
@@ -720,7 +720,6 @@ public class BeanFactoryAwareFunctionRegistry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (convertedValue == null) {
|
||||
@@ -734,10 +733,10 @@ public class BeanFactoryAwareFunctionRegistry
|
||||
Message outputMessage = null;
|
||||
if (value instanceof Message) {
|
||||
MessageHeaders headers = ((Message) value).getHeaders();
|
||||
if (!headers.containsKey(NegotiatingMessageConverterWrapper.ACCEPT)) {
|
||||
if (!headers.containsKey("accept")) {
|
||||
Map<String, Object> headersMap = (Map<String, Object>) ReflectionUtils
|
||||
.getField(this.headersField, headers);
|
||||
headersMap.put(NegotiatingMessageConverterWrapper.ACCEPT, acceptedContentType);
|
||||
headersMap.put("accept", acceptedContentType);
|
||||
// Set the contentType header to the value of accept for "legacy" reasons. But, do not set the
|
||||
// contentType header to the value of accept if it is a wildcard type, as this doesn't make sense.
|
||||
// This also applies to the else branch below.
|
||||
@@ -748,7 +747,7 @@ public class BeanFactoryAwareFunctionRegistry
|
||||
}
|
||||
else {
|
||||
MessageBuilder<Object> builder = MessageBuilder.withPayload(value)
|
||||
.setHeader(NegotiatingMessageConverterWrapper.ACCEPT, acceptedContentType);
|
||||
.setHeader("accept", acceptedContentType);
|
||||
if (acceptedContentType.isConcrete()) {
|
||||
builder.setHeader(MessageHeaders.CONTENT_TYPE, acceptedContentType);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ import org.springframework.cloud.function.context.FunctionProperties;
|
||||
import org.springframework.cloud.function.context.FunctionRegistry;
|
||||
import org.springframework.cloud.function.context.catalog.BeanFactoryAwareFunctionRegistry;
|
||||
import org.springframework.cloud.function.context.catalog.FunctionInspector;
|
||||
import org.springframework.cloud.function.context.catalog.NegotiatingMessageConverterWrapper;
|
||||
import org.springframework.cloud.function.json.GsonMapper;
|
||||
import org.springframework.cloud.function.json.JacksonMapper;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
@@ -51,6 +50,7 @@ import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.messaging.converter.AbstractMessageConverter;
|
||||
import org.springframework.messaging.converter.ByteArrayMessageConverter;
|
||||
import org.springframework.messaging.converter.CompositeMessageConverter;
|
||||
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
|
||||
@@ -84,13 +84,11 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
|
||||
CompositeMessageConverter messageConverter = null;
|
||||
List<MessageConverter> mcList = new ArrayList<>();
|
||||
boolean addDefaultConverters = true;
|
||||
|
||||
if (!CollectionUtils.isEmpty(messageConverters)) {
|
||||
for (MessageConverter mc : messageConverters) {
|
||||
if (mc instanceof CompositeMessageConverter) {
|
||||
mcList.addAll(((CompositeMessageConverter) mc).getConverters());
|
||||
addDefaultConverters = false;
|
||||
}
|
||||
else {
|
||||
mcList.add(mc);
|
||||
@@ -99,17 +97,20 @@ public class ContextFunctionCatalogAutoConfiguration {
|
||||
}
|
||||
|
||||
mcList = mcList.stream()
|
||||
.filter(c -> isConverterEligible(c)).collect(Collectors.toList());
|
||||
if (addDefaultConverters) {
|
||||
if (objectMapper == null) {
|
||||
objectMapper = new ObjectMapper();
|
||||
}
|
||||
MappingJackson2MessageConverter jsonConverter = new MappingJackson2MessageConverter();
|
||||
jsonConverter.setObjectMapper(objectMapper);
|
||||
mcList.add(NegotiatingMessageConverterWrapper.wrap(jsonConverter));
|
||||
mcList.add(NegotiatingMessageConverterWrapper.wrap(new ByteArrayMessageConverter()));
|
||||
mcList.add(NegotiatingMessageConverterWrapper.wrap(new StringMessageConverter()));
|
||||
}
|
||||
.filter(c -> isConverterEligible(c))
|
||||
.map(converter -> {
|
||||
return converter instanceof AbstractMessageConverter
|
||||
? NegotiatingMessageConverterWrapper.wrap((AbstractMessageConverter) converter)
|
||||
: converter;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
MappingJackson2MessageConverter jsonConverter = new MappingJackson2MessageConverter();
|
||||
jsonConverter.setObjectMapper(objectMapper == null ? new ObjectMapper() : objectMapper);
|
||||
mcList.add(NegotiatingMessageConverterWrapper.wrap(jsonConverter));
|
||||
mcList.add(NegotiatingMessageConverterWrapper.wrap(new ByteArrayMessageConverter()));
|
||||
mcList.add(NegotiatingMessageConverterWrapper.wrap(new StringMessageConverter()));
|
||||
|
||||
if (!CollectionUtils.isEmpty(mcList)) {
|
||||
messageConverter = new CompositeMessageConverter(mcList);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.function.context.catalog;
|
||||
package org.springframework.cloud.function.context.config;
|
||||
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
@@ -29,7 +29,7 @@ import org.springframework.util.MimeType;
|
||||
* contain a wildcard type (such as {@code text/*}, which may be tested against every
|
||||
* {@link AbstractMessageConverter#getSupportedMimeTypes() supported mime type} of the delegate MessageConverter.
|
||||
*/
|
||||
public final class NegotiatingMessageConverterWrapper implements SmartMessageConverter {
|
||||
final class NegotiatingMessageConverterWrapper implements SmartMessageConverter {
|
||||
|
||||
/**
|
||||
* The Message Header key that may contain the list of (possibly wildcard) MimeTypes to convert to.
|
||||
Reference in New Issue
Block a user