Merge changes for 22644
This commit is contained in:
commit
1c5aa6a8d3
|
|
@ -161,7 +161,7 @@ public abstract class MimeTypeUtils {
|
|||
|
||||
|
||||
private static final ConcurrentLruCache<String, MimeType> cachedMimeTypes =
|
||||
new ConcurrentLruCache<>(32, MimeTypeUtils::parseMimeTypeInternal);
|
||||
new ConcurrentLruCache<>(64, MimeTypeUtils::parseMimeTypeInternal);
|
||||
|
||||
@Nullable
|
||||
private static volatile Random random;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
|
|
@ -91,6 +91,7 @@ public class PathExtensionContentNegotiationStrategy extends AbstractMappingCont
|
|||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
// Ignore LOOKUP_PATH attribute, use our own "fixed" UrlPathHelper with decoding off
|
||||
String path = this.urlPathHelper.getLookupPathForRequest(request);
|
||||
String extension = UriUtils.extractFileExtension(path);
|
||||
return (StringUtils.hasText(extension) ? extension.toLowerCase(Locale.ENGLISH) : null);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2019 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,9 @@ public class UrlBasedCorsConfigurationSource implements CorsConfigurationSource
|
|||
|
||||
private UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||
|
||||
@Nullable
|
||||
private String lookupPathAttributeName;
|
||||
|
||||
|
||||
/**
|
||||
* Set the PathMatcher implementation to use for matching URL paths
|
||||
|
|
@ -72,6 +75,17 @@ public class UrlBasedCorsConfigurationSource implements CorsConfigurationSource
|
|||
this.urlPathHelper.setUrlDecode(urlDecode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally configure the name of the attribute that caches the lookupPath.
|
||||
* This is used to make the call to
|
||||
* {@link UrlPathHelper#getLookupPathForRequest(HttpServletRequest, String)}
|
||||
* @param lookupPathAttributeName the request attribute to check
|
||||
* @since 5.2
|
||||
*/
|
||||
public void setLookupPathAttributeName(@Nullable String lookupPathAttributeName) {
|
||||
this.lookupPathAttributeName = lookupPathAttributeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut to same property on underlying {@link #setUrlPathHelper UrlPathHelper}.
|
||||
* @see org.springframework.web.util.UrlPathHelper#setRemoveSemicolonContent(boolean)
|
||||
|
|
@ -117,7 +131,7 @@ public class UrlBasedCorsConfigurationSource implements CorsConfigurationSource
|
|||
@Override
|
||||
@Nullable
|
||||
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
|
||||
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
|
||||
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, this.lookupPathAttributeName);
|
||||
for (Map.Entry<String, CorsConfiguration> entry : this.corsConfigurations.entrySet()) {
|
||||
if (this.pathMatcher.match(entry.getKey(), lookupPath)) {
|
||||
return entry.getValue();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
|
|
@ -175,6 +175,26 @@ public class UrlPathHelper {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of {@link #getLookupPathForRequest(HttpServletRequest)} that
|
||||
* automates checking for a previously computed lookupPath saved as a
|
||||
* request attribute. The attribute is only used for lookup purposes.
|
||||
* @param request current HTTP request
|
||||
* @param lookupPathAttributeName the request attribute to check
|
||||
* @return the lookup path
|
||||
* @since 5.2
|
||||
* @see org.springframework.web.servlet.HandlerMapping#LOOKUP_PATH
|
||||
*/
|
||||
public String getLookupPathForRequest(HttpServletRequest request, @Nullable String lookupPathAttributeName) {
|
||||
if (lookupPathAttributeName != null) {
|
||||
String result = (String) request.getAttribute(lookupPathAttributeName);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return getLookupPathForRequest(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the path within the servlet mapping for the given request,
|
||||
* i.e. the part of the request's URL beyond the part that called the servlet,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ import java.util.Set;
|
|||
|
||||
import org.springframework.http.InvalidMediaTypeException;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.cors.reactive.CorsUtils;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
|
@ -68,15 +70,16 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
|
|||
* @param headers as described in {@link RequestMapping#headers()}
|
||||
*/
|
||||
public ConsumesRequestCondition(String[] consumes, String[] headers) {
|
||||
this(parseExpressions(consumes, headers));
|
||||
this.expressions = new ArrayList<>(parseExpressions(consumes, headers));
|
||||
Collections.sort(this.expressions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor accepting parsed media type expressions.
|
||||
* Private constructor for internal when creating matching conditions.
|
||||
* Note the expressions List is neither sorted nor deep copied.
|
||||
*/
|
||||
private ConsumesRequestCondition(Collection<ConsumeMediaTypeExpression> expressions) {
|
||||
this.expressions = new ArrayList<>(expressions);
|
||||
Collections.sort(this.expressions);
|
||||
private ConsumesRequestCondition(List<ConsumeMediaTypeExpression> expressions) {
|
||||
this.expressions = expressions;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -166,9 +169,20 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
|
|||
if (isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
Set<ConsumeMediaTypeExpression> result = new LinkedHashSet<>(this.expressions);
|
||||
result.removeIf(expression -> !expression.match(exchange));
|
||||
return (!result.isEmpty() ? new ConsumesRequestCondition(result) : null);
|
||||
List<ConsumeMediaTypeExpression> result = getMatchingExpressions(exchange);
|
||||
return !CollectionUtils.isEmpty(result) ? new ConsumesRequestCondition(result) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private List<ConsumeMediaTypeExpression> getMatchingExpressions(ServerWebExchange exchange) {
|
||||
List<ConsumeMediaTypeExpression> result = null;
|
||||
for (ConsumeMediaTypeExpression expression : this.expressions) {
|
||||
if (expression.match(exchange)) {
|
||||
result = result != null ? result : new ArrayList<>();
|
||||
result.add(expression);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.web.reactive.result.condition;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
|
@ -56,12 +55,12 @@ public final class HeadersRequestCondition extends AbstractRequestCondition<Head
|
|||
this(parseExpressions(headers));
|
||||
}
|
||||
|
||||
private HeadersRequestCondition(Collection<HeaderExpression> conditions) {
|
||||
this.expressions = Collections.unmodifiableSet(new LinkedHashSet<>(conditions));
|
||||
private HeadersRequestCondition(Set<HeaderExpression> conditions) {
|
||||
this.expressions = conditions;
|
||||
}
|
||||
|
||||
|
||||
private static Collection<HeaderExpression> parseExpressions(String... headers) {
|
||||
private static Set<HeaderExpression> parseExpressions(String... headers) {
|
||||
Set<HeaderExpression> expressions = new LinkedHashSet<>();
|
||||
if (headers != null) {
|
||||
for (String header : headers) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.web.reactive.result.condition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
|
@ -25,11 +24,11 @@ import java.util.Set;
|
|||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.accept.ContentNegotiationManager;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.cors.reactive.CorsUtils;
|
||||
import org.springframework.web.reactive.accept.HeaderContentTypeResolver;
|
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
|
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder;
|
||||
import org.springframework.web.server.NotAcceptableStatusException;
|
||||
|
|
@ -48,8 +47,13 @@ import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
|||
*/
|
||||
public final class ProducesRequestCondition extends AbstractRequestCondition<ProducesRequestCondition> {
|
||||
|
||||
private static final RequestedContentTypeResolver DEFAULT_CONTENT_TYPE_RESOLVER =
|
||||
new RequestedContentTypeResolverBuilder().build();
|
||||
|
||||
private static final ProducesRequestCondition EMPTY_CONDITION = new ProducesRequestCondition();
|
||||
|
||||
private static final String MEDIA_TYPES_ATTRIBUTE = ProducesRequestCondition.class.getName() + ".MEDIA_TYPES";
|
||||
|
||||
|
||||
private final List<ProduceMediaTypeExpression> mediaTypeAllList =
|
||||
Collections.singletonList(new ProduceMediaTypeExpression(MediaType.ALL_VALUE));
|
||||
|
|
@ -90,18 +94,16 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
|
|||
public ProducesRequestCondition(String[] produces, String[] headers, RequestedContentTypeResolver resolver) {
|
||||
this.expressions = new ArrayList<>(parseExpressions(produces, headers));
|
||||
Collections.sort(this.expressions);
|
||||
this.contentTypeResolver = (resolver != null ? resolver : new HeaderContentTypeResolver());
|
||||
this.contentTypeResolver = resolver != null ? resolver : DEFAULT_CONTENT_TYPE_RESOLVER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor with already parsed media type expressions.
|
||||
* Private constructor for internal use to create matching conditions.
|
||||
* Note the expressions List is neither sorted, nor deep copied.
|
||||
*/
|
||||
private ProducesRequestCondition(Collection<ProduceMediaTypeExpression> expressions,
|
||||
RequestedContentTypeResolver resolver) {
|
||||
|
||||
this.expressions = new ArrayList<>(expressions);
|
||||
Collections.sort(this.expressions);
|
||||
this.contentTypeResolver = (resolver != null ? resolver : new RequestedContentTypeResolverBuilder().build());
|
||||
private ProducesRequestCondition(List<ProduceMediaTypeExpression> expressions, ProducesRequestCondition other) {
|
||||
this.expressions = expressions;
|
||||
this.contentTypeResolver = other.contentTypeResolver;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -189,10 +191,9 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
|
|||
if (isEmpty() || CorsUtils.isPreFlightRequest(exchange.getRequest())) {
|
||||
return EMPTY_CONDITION;
|
||||
}
|
||||
Set<ProduceMediaTypeExpression> result = new LinkedHashSet<>(this.expressions);
|
||||
result.removeIf(expression -> !expression.match(exchange));
|
||||
if (!result.isEmpty()) {
|
||||
return new ProducesRequestCondition(result, this.contentTypeResolver);
|
||||
List<ProduceMediaTypeExpression> result = getMatchingExpressions(exchange);
|
||||
if (!CollectionUtils.isEmpty(result)) {
|
||||
return new ProducesRequestCondition(result, this);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
|
|
@ -207,6 +208,18 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
|
|||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private List<ProduceMediaTypeExpression> getMatchingExpressions(ServerWebExchange exchange) {
|
||||
List<ProduceMediaTypeExpression> result = null;
|
||||
for (ProduceMediaTypeExpression expression : this.expressions) {
|
||||
if (expression.match(exchange)) {
|
||||
result = result != null ? result : new ArrayList<>();
|
||||
result.add(expression);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this and another "produces" condition as follows:
|
||||
* <ol>
|
||||
|
|
@ -251,7 +264,12 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
|
|||
}
|
||||
|
||||
private List<MediaType> getAcceptedMediaTypes(ServerWebExchange exchange) throws NotAcceptableStatusException {
|
||||
return this.contentTypeResolver.resolveMediaTypes(exchange);
|
||||
List<MediaType> result = exchange.getAttribute(MEDIA_TYPES_ATTRIBUTE);
|
||||
if (result == null) {
|
||||
result = this.contentTypeResolver.resolveMediaTypes(exchange);
|
||||
exchange.getAttributes().put(MEDIA_TYPES_ATTRIBUTE, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int indexOfEqualMediaType(MediaType mediaType) {
|
||||
|
|
|
|||
|
|
@ -19,8 +19,10 @@ package org.springframework.web.reactive.result.condition;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
|
@ -39,8 +41,15 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
*/
|
||||
public final class RequestMethodsRequestCondition extends AbstractRequestCondition<RequestMethodsRequestCondition> {
|
||||
|
||||
private static final RequestMethodsRequestCondition GET_CONDITION =
|
||||
new RequestMethodsRequestCondition(RequestMethod.GET);
|
||||
/** Per HTTP method cache to return ready instances from getMatchingCondition. */
|
||||
private static final Map<String, RequestMethodsRequestCondition> requestMethodConditionCache;
|
||||
|
||||
static {
|
||||
requestMethodConditionCache = new HashMap<>(RequestMethod.values().length);
|
||||
for (RequestMethod method : RequestMethod.values()) {
|
||||
requestMethodConditionCache.put(method.name(), new RequestMethodsRequestCondition(method));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final Set<RequestMethod> methods;
|
||||
|
|
@ -110,11 +119,11 @@ public final class RequestMethodsRequestCondition extends AbstractRequestConditi
|
|||
}
|
||||
if (getMethods().isEmpty()) {
|
||||
if (RequestMethod.OPTIONS.name().equals(exchange.getRequest().getMethodValue())) {
|
||||
return null; // No implicit match for OPTIONS (we handle it)
|
||||
return null; // We handle OPTIONS transparently, so don't match if no explicit declarations
|
||||
}
|
||||
return this;
|
||||
}
|
||||
return matchRequestMethod(exchange.getRequest().getMethod());
|
||||
return matchRequestMethod(exchange.getRequest().getMethodValue());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -122,24 +131,25 @@ public final class RequestMethodsRequestCondition extends AbstractRequestConditi
|
|||
* Hence empty conditions is a match, otherwise try to match to the HTTP
|
||||
* method in the "Access-Control-Request-Method" header.
|
||||
*/
|
||||
@Nullable
|
||||
private RequestMethodsRequestCondition matchPreFlight(ServerHttpRequest request) {
|
||||
if (getMethods().isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
HttpMethod expectedMethod = request.getHeaders().getAccessControlRequestMethod();
|
||||
return matchRequestMethod(expectedMethod);
|
||||
return expectedMethod != null ? matchRequestMethod(expectedMethod.name()) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private RequestMethodsRequestCondition matchRequestMethod(@Nullable HttpMethod httpMethod) {
|
||||
private RequestMethodsRequestCondition matchRequestMethod(@Nullable String httpMethod) {
|
||||
if (httpMethod != null) {
|
||||
for (RequestMethod method : getMethods()) {
|
||||
if (httpMethod.matches(method.name())) {
|
||||
return new RequestMethodsRequestCondition(method);
|
||||
return requestMethodConditionCache.get(method.name());
|
||||
}
|
||||
}
|
||||
if (httpMethod == HttpMethod.HEAD && getMethods().contains(RequestMethod.GET)) {
|
||||
return GET_CONDITION;
|
||||
if (HttpMethod.HEAD.matches(httpMethod) && getMethods().contains(RequestMethod.GET)) {
|
||||
return requestMethodConditionCache.get(HttpMethod.GET.name());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -62,6 +62,15 @@ public interface HandlerMapping {
|
|||
*/
|
||||
String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler";
|
||||
|
||||
/**
|
||||
* Name of the {@link HttpServletRequest} attribute that contains the path
|
||||
* used to look up the matching handler, which depending on the configured
|
||||
* {@link org.springframework.web.util.UrlPathHelper} could be the full path
|
||||
* or without the context path, decoded or not, etc.
|
||||
* @since 5.2
|
||||
*/
|
||||
String LOOKUP_PATH = HandlerMapping.class.getName() + ".lookupPath";
|
||||
|
||||
/**
|
||||
* Name of the {@link HttpServletRequest} attribute that contains the path
|
||||
* within the handler mapping, in case of a pattern match, or the full
|
||||
|
|
|
|||
|
|
@ -212,6 +212,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
|
|||
source.setCorsConfigurations(corsConfigurations);
|
||||
source.setPathMatcher(this.pathMatcher);
|
||||
source.setUrlPathHelper(this.urlPathHelper);
|
||||
source.setLookupPathAttributeName(LOOKUP_PATH);
|
||||
this.corsConfigurationSource = source;
|
||||
}
|
||||
else {
|
||||
|
|
@ -463,7 +464,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
|
|||
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
|
||||
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
|
||||
|
||||
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
|
||||
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
|
||||
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
|
||||
if (interceptor instanceof MappedInterceptor) {
|
||||
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
|
||||
|
|
|
|||
|
|
@ -355,6 +355,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
|
|||
@Override
|
||||
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
|
||||
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
|
||||
request.setAttribute(LOOKUP_PATH, lookupPath);
|
||||
this.mappingRegistry.acquireReadLock();
|
||||
try {
|
||||
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i
|
|||
@Nullable
|
||||
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
|
||||
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
|
||||
request.setAttribute(LOOKUP_PATH, lookupPath);
|
||||
Object handler = lookupHandler(lookupPath, request);
|
||||
if (handler == null) {
|
||||
// We need to care for the default handler directly, since we need to
|
||||
|
|
@ -291,7 +292,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i
|
|||
@Override
|
||||
@Nullable
|
||||
public RequestMatchResult match(HttpServletRequest request, String pattern) {
|
||||
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
|
||||
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request, LOOKUP_PATH);
|
||||
if (getPathMatcher().match(pattern, lookupPath)) {
|
||||
return new RequestMatchResult(pattern, lookupPath, getPathMatcher());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
|
|
@ -110,7 +110,7 @@ public class UrlFilenameViewController extends AbstractUrlViewController {
|
|||
protected String extractOperableUrl(HttpServletRequest request) {
|
||||
String urlPath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
|
||||
if (!StringUtils.hasText(urlPath)) {
|
||||
urlPath = getUrlPathHelper().getLookupPathForRequest(request);
|
||||
urlPath = getUrlPathHelper().getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
|
||||
}
|
||||
return urlPath;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
|
|
@ -30,6 +30,7 @@ import org.springframework.util.AntPathMatcher;
|
|||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.support.WebContentGenerator;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
|
@ -169,7 +170,7 @@ public class WebContentInterceptor extends WebContentGenerator implements Handle
|
|||
|
||||
checkRequest(request);
|
||||
|
||||
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
|
||||
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
|
||||
|
||||
CacheControl cacheControl = lookupCacheControl(lookupPath);
|
||||
Integer cacheSeconds = lookupCacheSeconds(lookupPath);
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ abstract class AbstractNameValueExpression<T> implements NameValueExpression<T>
|
|||
else {
|
||||
isMatch = matchName(request);
|
||||
}
|
||||
return (this.isNegated ? !isMatch : isMatch);
|
||||
return this.isNegated != isMatch;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import org.springframework.http.InvalidMediaTypeException;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.cors.CorsUtils;
|
||||
|
|
@ -70,15 +71,16 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
|
|||
* @param headers as described in {@link RequestMapping#headers()}
|
||||
*/
|
||||
public ConsumesRequestCondition(String[] consumes, @Nullable String[] headers) {
|
||||
this(parseExpressions(consumes, headers));
|
||||
this.expressions = new ArrayList<>(parseExpressions(consumes, headers));
|
||||
Collections.sort(this.expressions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor accepting parsed media type expressions.
|
||||
* Private constructor for internal when creating matching conditions.
|
||||
* Note the expressions List is neither sorted nor deep copied.
|
||||
*/
|
||||
private ConsumesRequestCondition(Collection<ConsumeMediaTypeExpression> expressions) {
|
||||
this.expressions = new ArrayList<>(expressions);
|
||||
Collections.sort(this.expressions);
|
||||
private ConsumesRequestCondition(List<ConsumeMediaTypeExpression> expressions) {
|
||||
this.expressions = expressions;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -169,6 +171,8 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
|
|||
return this;
|
||||
}
|
||||
|
||||
// Common media types are cached at the level of MimeTypeUtils
|
||||
|
||||
MediaType contentType;
|
||||
try {
|
||||
contentType = (StringUtils.hasLength(request.getContentType()) ?
|
||||
|
|
@ -179,9 +183,20 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
|
|||
return null;
|
||||
}
|
||||
|
||||
Set<ConsumeMediaTypeExpression> result = new LinkedHashSet<>(this.expressions);
|
||||
result.removeIf(expression -> !expression.match(contentType));
|
||||
return (!result.isEmpty() ? new ConsumesRequestCondition(result) : null);
|
||||
List<ConsumeMediaTypeExpression> result = getMatchingExpressions(contentType);
|
||||
return !CollectionUtils.isEmpty(result) ? new ConsumesRequestCondition(result) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private List<ConsumeMediaTypeExpression> getMatchingExpressions(MediaType contentType) {
|
||||
List<ConsumeMediaTypeExpression> result = null;
|
||||
for (ConsumeMediaTypeExpression expression : this.expressions) {
|
||||
if (expression.match(contentType)) {
|
||||
result = result != null ? result : new ArrayList<>();
|
||||
result.add(expression);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.web.servlet.mvc.condition;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
|
@ -58,12 +57,12 @@ public final class HeadersRequestCondition extends AbstractRequestCondition<Head
|
|||
this(parseExpressions(headers));
|
||||
}
|
||||
|
||||
private HeadersRequestCondition(Collection<HeaderExpression> conditions) {
|
||||
this.expressions = Collections.unmodifiableSet(new LinkedHashSet<>(conditions));
|
||||
private HeadersRequestCondition(Set<HeaderExpression> conditions) {
|
||||
this.expressions = conditions;
|
||||
}
|
||||
|
||||
|
||||
private static Collection<HeaderExpression> parseExpressions(String... headers) {
|
||||
private static Set<HeaderExpression> parseExpressions(String... headers) {
|
||||
Set<HeaderExpression> expressions = new LinkedHashSet<>();
|
||||
for (String header : headers) {
|
||||
HeaderExpression expr = new HeaderExpression(header);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
|
|
@ -18,6 +18,7 @@ package org.springframework.web.servlet.mvc.condition;
|
|||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
|
@ -142,8 +143,15 @@ public final class ParamsRequestCondition extends AbstractRequestCondition<Param
|
|||
*/
|
||||
static class ParamExpression extends AbstractNameValueExpression<String> {
|
||||
|
||||
private final Set<String> namesToMatch = new HashSet<>(WebUtils.SUBMIT_IMAGE_SUFFIXES.length + 1);
|
||||
|
||||
|
||||
ParamExpression(String expression) {
|
||||
super(expression);
|
||||
this.namesToMatch.add(getName());
|
||||
for (String suffix : WebUtils.SUBMIT_IMAGE_SUFFIXES) {
|
||||
this.namesToMatch.add(getName() + suffix);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -158,8 +166,12 @@ public final class ParamsRequestCondition extends AbstractRequestCondition<Param
|
|||
|
||||
@Override
|
||||
protected boolean matchName(HttpServletRequest request) {
|
||||
return (WebUtils.hasSubmitParameter(request, this.name) ||
|
||||
request.getParameterMap().containsKey(this.name));
|
||||
for (String current : this.namesToMatch) {
|
||||
if (request.getParameterMap().get(current) != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return request.getParameterMap().containsKey(this.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import org.springframework.lang.Nullable;
|
|||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
||||
/**
|
||||
|
|
@ -105,8 +106,8 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
|
|||
boolean useTrailingSlashMatch, @Nullable List<String> fileExtensions) {
|
||||
|
||||
this.patterns = Collections.unmodifiableSet(prependLeadingSlash(patterns));
|
||||
this.pathHelper = (urlPathHelper != null ? urlPathHelper : new UrlPathHelper());
|
||||
this.pathMatcher = (pathMatcher != null ? pathMatcher : new AntPathMatcher());
|
||||
this.pathHelper = urlPathHelper != null ? urlPathHelper : new UrlPathHelper();
|
||||
this.pathMatcher = pathMatcher != null ? pathMatcher : new AntPathMatcher();
|
||||
this.useSuffixPatternMatch = useSuffixPatternMatch;
|
||||
this.useTrailingSlashMatch = useTrailingSlashMatch;
|
||||
|
||||
|
|
@ -120,6 +121,18 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor for use when combining and matching.
|
||||
*/
|
||||
private PatternsRequestCondition(Set<String> patterns, PatternsRequestCondition other) {
|
||||
this.patterns = patterns;
|
||||
this.pathHelper = other.pathHelper;
|
||||
this.pathMatcher = other.pathMatcher;
|
||||
this.useSuffixPatternMatch = other.useSuffixPatternMatch;
|
||||
this.useTrailingSlashMatch = other.useTrailingSlashMatch;
|
||||
this.fileExtensions.addAll(other.fileExtensions);
|
||||
}
|
||||
|
||||
|
||||
private static Set<String> prependLeadingSlash(Collection<String> patterns) {
|
||||
Set<String> result = new LinkedHashSet<>(patterns.size());
|
||||
|
|
@ -175,8 +188,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
|
|||
else {
|
||||
result.add("");
|
||||
}
|
||||
return new PatternsRequestCondition(result, this.pathHelper, this.pathMatcher,
|
||||
this.useSuffixPatternMatch, this.useTrailingSlashMatch, this.fileExtensions);
|
||||
return new PatternsRequestCondition(result, this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -201,30 +213,31 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
|
|||
if (this.patterns.isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
String lookupPath = this.pathHelper.getLookupPathForRequest(request);
|
||||
String lookupPath = this.pathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
|
||||
List<String> matches = getMatchingPatterns(lookupPath);
|
||||
return (!matches.isEmpty() ?
|
||||
new PatternsRequestCondition(matches, this.pathHelper, this.pathMatcher,
|
||||
this.useSuffixPatternMatch, this.useTrailingSlashMatch, this.fileExtensions) : null);
|
||||
return !matches.isEmpty() ? new PatternsRequestCondition(new LinkedHashSet<>(matches), this) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the patterns matching the given lookup path. Invoking this method should
|
||||
* yield results equivalent to those of calling
|
||||
* {@link #getMatchingCondition(javax.servlet.http.HttpServletRequest)}.
|
||||
* yield results equivalent to those of calling {@link #getMatchingCondition}.
|
||||
* This method is provided as an alternative to be used if no request is available
|
||||
* (e.g. introspection, tooling, etc).
|
||||
* @param lookupPath the lookup path to match to existing patterns
|
||||
* @return a collection of matching patterns sorted with the closest match at the top
|
||||
*/
|
||||
public List<String> getMatchingPatterns(String lookupPath) {
|
||||
List<String> matches = new ArrayList<>();
|
||||
List<String> matches = null;
|
||||
for (String pattern : this.patterns) {
|
||||
String match = getMatchingPattern(pattern, lookupPath);
|
||||
if (match != null) {
|
||||
matches = matches != null ? matches : new ArrayList<>();
|
||||
matches.add(match);
|
||||
}
|
||||
}
|
||||
if (matches == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (matches.size() > 1) {
|
||||
matches.sort(this.pathMatcher.getPatternComparator(lookupPath));
|
||||
}
|
||||
|
|
@ -275,7 +288,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
|
|||
*/
|
||||
@Override
|
||||
public int compareTo(PatternsRequestCondition other, HttpServletRequest request) {
|
||||
String lookupPath = this.pathHelper.getLookupPathForRequest(request);
|
||||
String lookupPath = this.pathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
|
||||
Comparator<String> patternComparator = this.pathMatcher.getPatternComparator(lookupPath);
|
||||
Iterator<String> iterator = this.patterns.iterator();
|
||||
Iterator<String> iteratorOther = other.patterns.iterator();
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package org.springframework.web.servlet.mvc.condition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
|
@ -26,6 +25,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.HttpMediaTypeException;
|
||||
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
|
|
@ -48,11 +48,16 @@ import org.springframework.web.servlet.mvc.condition.HeadersRequestCondition.Hea
|
|||
*/
|
||||
public final class ProducesRequestCondition extends AbstractRequestCondition<ProducesRequestCondition> {
|
||||
|
||||
private static final ContentNegotiationManager DEFAULT_CONTENT_NEGOTIATION_MANAGER =
|
||||
new ContentNegotiationManager();
|
||||
|
||||
private static final ProducesRequestCondition EMPTY_CONDITION = new ProducesRequestCondition();
|
||||
|
||||
private static final List<ProduceMediaTypeExpression> MEDIA_TYPE_ALL_LIST =
|
||||
Collections.singletonList(new ProduceMediaTypeExpression(MediaType.ALL_VALUE));
|
||||
|
||||
private static final String MEDIA_TYPES_ATTRIBUTE = ProducesRequestCondition.class.getName() + ".MEDIA_TYPES";
|
||||
|
||||
|
||||
private final List<ProduceMediaTypeExpression> expressions;
|
||||
|
||||
|
|
@ -92,18 +97,16 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
|
|||
|
||||
this.expressions = new ArrayList<>(parseExpressions(produces, headers));
|
||||
Collections.sort(this.expressions);
|
||||
this.contentNegotiationManager = (manager != null ? manager : new ContentNegotiationManager());
|
||||
this.contentNegotiationManager = manager != null ? manager : DEFAULT_CONTENT_NEGOTIATION_MANAGER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor with already parsed media type expressions.
|
||||
* Private constructor for internal use to create matching conditions.
|
||||
* Note the expressions List is neither sorted nor deep copied.
|
||||
*/
|
||||
private ProducesRequestCondition(Collection<ProduceMediaTypeExpression> expressions,
|
||||
@Nullable ContentNegotiationManager manager) {
|
||||
|
||||
this.expressions = new ArrayList<>(expressions);
|
||||
Collections.sort(this.expressions);
|
||||
this.contentNegotiationManager = (manager != null ? manager : new ContentNegotiationManager());
|
||||
private ProducesRequestCondition(List<ProduceMediaTypeExpression> expressions, ProducesRequestCondition other) {
|
||||
this.expressions = expressions;
|
||||
this.contentNegotiationManager = other.contentNegotiationManager;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -198,10 +201,9 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
|
|||
return null;
|
||||
}
|
||||
|
||||
Set<ProduceMediaTypeExpression> result = new LinkedHashSet<>(this.expressions);
|
||||
result.removeIf(expression -> !expression.match(acceptedMediaTypes));
|
||||
if (!result.isEmpty()) {
|
||||
return new ProducesRequestCondition(result, this.contentNegotiationManager);
|
||||
List<ProduceMediaTypeExpression> result = getMatchingExpressions(acceptedMediaTypes);
|
||||
if (!CollectionUtils.isEmpty(result)) {
|
||||
return new ProducesRequestCondition(result, this);
|
||||
}
|
||||
else if (MediaType.ALL.isPresentIn(acceptedMediaTypes)) {
|
||||
return EMPTY_CONDITION;
|
||||
|
|
@ -211,6 +213,18 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
|
|||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private List<ProduceMediaTypeExpression> getMatchingExpressions(List<MediaType> acceptedMediaTypes) {
|
||||
List<ProduceMediaTypeExpression> result = null;
|
||||
for (ProduceMediaTypeExpression expression : this.expressions) {
|
||||
if (expression.match(acceptedMediaTypes)) {
|
||||
result = result != null ? result : new ArrayList<>();
|
||||
result.add(expression);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this and another "produces" condition as follows:
|
||||
* <ol>
|
||||
|
|
@ -254,8 +268,16 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
|
|||
}
|
||||
}
|
||||
|
||||
private List<MediaType> getAcceptedMediaTypes(HttpServletRequest request) throws HttpMediaTypeNotAcceptableException {
|
||||
return this.contentNegotiationManager.resolveMediaTypes(new ServletWebRequest(request));
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<MediaType> getAcceptedMediaTypes(HttpServletRequest request)
|
||||
throws HttpMediaTypeNotAcceptableException {
|
||||
|
||||
List<MediaType> result = (List<MediaType>) request.getAttribute(MEDIA_TYPES_ATTRIBUTE);
|
||||
if (result == null) {
|
||||
result = this.contentNegotiationManager.resolveMediaTypes(new ServletWebRequest(request));
|
||||
request.setAttribute(MEDIA_TYPES_ATTRIBUTE, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int indexOfEqualMediaType(MediaType mediaType) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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,7 +19,9 @@ package org.springframework.web.servlet.mvc.condition;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
|
@ -40,8 +42,16 @@ import org.springframework.web.cors.CorsUtils;
|
|||
*/
|
||||
public final class RequestMethodsRequestCondition extends AbstractRequestCondition<RequestMethodsRequestCondition> {
|
||||
|
||||
private static final RequestMethodsRequestCondition GET_CONDITION =
|
||||
new RequestMethodsRequestCondition(RequestMethod.GET);
|
||||
/** Per HTTP method cache to return ready instances from getMatchingCondition. */
|
||||
private static final Map<String, RequestMethodsRequestCondition> requestMethodConditionCache;
|
||||
|
||||
static {
|
||||
requestMethodConditionCache = new HashMap<>(RequestMethod.values().length);
|
||||
for (RequestMethod method : RequestMethod.values()) {
|
||||
requestMethodConditionCache.put(method.name(), new RequestMethodsRequestCondition(method));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final Set<RequestMethod> methods;
|
||||
|
||||
|
|
@ -108,7 +118,7 @@ public final class RequestMethodsRequestCondition extends AbstractRequestConditi
|
|||
if (RequestMethod.OPTIONS.name().equals(request.getMethod()) &&
|
||||
!DispatcherType.ERROR.equals(request.getDispatcherType())) {
|
||||
|
||||
return null; // No implicit match for OPTIONS (we handle it)
|
||||
return null; // We handle OPTIONS transparently, so don't match if no explicit declarations
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
@ -136,11 +146,11 @@ public final class RequestMethodsRequestCondition extends AbstractRequestConditi
|
|||
if (httpMethod != null) {
|
||||
for (RequestMethod method : getMethods()) {
|
||||
if (httpMethod.matches(method.name())) {
|
||||
return new RequestMethodsRequestCondition(method);
|
||||
return requestMethodConditionCache.get(method.name());
|
||||
}
|
||||
}
|
||||
if (httpMethod == HttpMethod.HEAD && getMethods().contains(RequestMethod.GET)) {
|
||||
return GET_CONDITION;
|
||||
return requestMethodConditionCache.get(HttpMethod.GET.name());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
|
|
@ -340,7 +340,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
|||
return null;
|
||||
}
|
||||
Set<String> patterns = matchingInfo.getPatternsCondition().getPatterns();
|
||||
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
|
||||
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request, LOOKUP_PATH);
|
||||
return new RequestMatchResult(patterns.iterator().next(), lookupPath, getPathMatcher());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
|
|
@ -34,6 +34,7 @@ import org.springframework.lang.Nullable;
|
|||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
||||
|
|
@ -180,7 +181,7 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed
|
|||
private int getLookupPathIndex(HttpServletRequest request) {
|
||||
UrlPathHelper pathHelper = getUrlPathHelper();
|
||||
String requestUri = pathHelper.getRequestUri(request);
|
||||
String lookupPath = pathHelper.getLookupPathForRequest(request);
|
||||
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
|
||||
return requestUri.indexOf(lookupPath);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
|
|
@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.RequestToViewNameTranslator;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
||||
|
|
@ -167,7 +168,7 @@ public class DefaultRequestToViewNameTranslator implements RequestToViewNameTran
|
|||
*/
|
||||
@Override
|
||||
public String getViewName(HttpServletRequest request) {
|
||||
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
|
||||
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, HandlerMapping.LOOKUP_PATH);
|
||||
return (this.prefix + transformPath(lookupPath) + this.suffix);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue