Remove producible request attribute before mapping

The attribute was previously removed only before exception resolution
in the DispatcherServlet in order to allow error rendering to make an
independent choice on content negotation.

However, Boot rendering happens later in an ERROR dispatch which could
also be a nested dispatch on some servers. So the attribute must also
generally be removed prior to mapping.

We also move the methods where this is done to the base
RequestMappingInfoHandlerMapping class which also deals with the
produces condition and where the producible attribute is added in the
first place.

Closes gh-24466
This commit is contained in:
Rossen Stoyanchev
2020-02-18 21:50:38 +00:00
parent 87f866b688
commit 68b980f849
4 changed files with 24 additions and 23 deletions

View File

@@ -27,6 +27,8 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import reactor.core.publisher.Mono;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.InvalidMediaTypeException;
@@ -38,6 +40,7 @@ import org.springframework.util.MultiValueMap;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.reactive.HandlerMapping;
import org.springframework.web.reactive.result.condition.NameValueExpression;
import org.springframework.web.reactive.result.condition.ProducesRequestCondition;
import org.springframework.web.server.MethodNotAllowedException;
import org.springframework.web.server.NotAcceptableStatusException;
import org.springframework.web.server.ServerWebExchange;
@@ -87,6 +90,13 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
return (info1, info2) -> info1.compareTo(info2, exchange);
}
@Override
public Mono<HandlerMethod> getHandlerInternal(ServerWebExchange exchange) {
exchange.getAttributes().remove(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
return super.getHandlerInternal(exchange)
.doOnTerminate(() -> ProducesRequestCondition.clearMediaTypesAttribute(exchange));
}
/**
* Expose URI template variables, matrix variables, and producible media types in the request.
* @see HandlerMapping#URI_TEMPLATE_VARIABLES_ATTRIBUTE

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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.
@@ -24,8 +24,6 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Predicate;
import reactor.core.publisher.Mono;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.MergedAnnotation;
@@ -45,11 +43,9 @@ import org.springframework.web.method.HandlerMethod;
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder;
import org.springframework.web.reactive.result.condition.ConsumesRequestCondition;
import org.springframework.web.reactive.result.condition.ProducesRequestCondition;
import org.springframework.web.reactive.result.condition.RequestCondition;
import org.springframework.web.reactive.result.method.RequestMappingInfo;
import org.springframework.web.reactive.result.method.RequestMappingInfoHandlerMapping;
import org.springframework.web.server.ServerWebExchange;
/**
* An extension of {@link RequestMappingInfoHandlerMapping} that creates
@@ -356,10 +352,4 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
}
}
@Override
public Mono<HandlerMethod> getHandlerInternal(ServerWebExchange exchange) {
return super.getHandlerInternal(exchange)
.doOnTerminate(() -> ProducesRequestCondition.clearMediaTypesAttribute(exchange));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2020 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.
@@ -45,6 +45,7 @@ import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping;
import org.springframework.web.servlet.mvc.condition.NameValueExpression;
import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition;
import org.springframework.web.util.WebUtils;
/**
@@ -102,6 +103,17 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
return (info1, info2) -> info1.compareTo(info2, request);
}
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
try {
return super.getHandlerInternal(request);
}
finally {
ProducesRequestCondition.clearMediaTypesAttribute(request);
}
}
/**
* Expose URI template variables, matrix variables, and producible media types in the request.
* @see HandlerMapping#URI_TEMPLATE_VARIABLES_ATTRIBUTE

View File

@@ -49,7 +49,6 @@ import org.springframework.web.servlet.handler.RequestMatchResult;
import org.springframework.web.servlet.mvc.condition.AbstractRequestCondition;
import org.springframework.web.servlet.mvc.condition.CompositeRequestCondition;
import org.springframework.web.servlet.mvc.condition.ConsumesRequestCondition;
import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
@@ -473,14 +472,4 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
}
}
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
try {
return super.getHandlerInternal(request);
}
finally {
ProducesRequestCondition.clearMediaTypesAttribute(request);
}
}
}