Expose mapped handler as an exchange attribute
Issue: SPR-15564
This commit is contained in:
parent
58a5e7f17b
commit
67330dfc23
|
@ -31,29 +31,31 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
public interface HandlerMapping {
|
||||
|
||||
/**
|
||||
* Name of the {@link ServerWebExchange} attribute that contains the
|
||||
* best matching pattern within the handler mapping.
|
||||
* <p>Note: This attribute is not required to be supported by all
|
||||
* HandlerMapping implementations. URL-based HandlerMappings will
|
||||
* typically support it, but handlers should not necessarily expect
|
||||
* this request attribute to be present in all scenarios.
|
||||
* Name of the {@link ServerWebExchange#getAttributes() attribute} that
|
||||
* contains the mapped handler for the best matching pattern.
|
||||
*/
|
||||
String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler";
|
||||
|
||||
/**
|
||||
* Name of the {@link ServerWebExchange#getAttributes() attribute} that
|
||||
* contains the best matching pattern within the handler mapping.
|
||||
*/
|
||||
String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
|
||||
|
||||
/**
|
||||
* Name of the {@link ServerWebExchange} attribute that contains the path
|
||||
* within the handler mapping, in case of a pattern match, or the full
|
||||
* relevant URI (typically within the DispatcherServlet's mapping) else.
|
||||
* Name of the {@link ServerWebExchange#getAttributes() attribute} that
|
||||
* contains the path within the handler mapping, in case of a pattern match
|
||||
* such as {@code "/static/**"} or the full relevant URI otherwise.
|
||||
* <p>Note: This attribute is not required to be supported by all
|
||||
* HandlerMapping implementations. URL-based HandlerMappings will
|
||||
* typically support it, but handlers should not necessarily expect
|
||||
* typically support it but handlers should not necessarily expect
|
||||
* this request attribute to be present in all scenarios.
|
||||
*/
|
||||
String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
|
||||
|
||||
/**
|
||||
* Name of the {@link ServerWebExchange} attribute that contains the URI
|
||||
* templates map, mapping variable names to values.
|
||||
* Name of the {@link ServerWebExchange#getAttributes() attribute} that
|
||||
* contains the URI templates map mapping variable names to values.
|
||||
* <p>Note: This attribute is not required to be supported by all
|
||||
* HandlerMapping implementations. URL-based HandlerMappings will
|
||||
* typically support it, but handlers should not necessarily expect
|
||||
|
@ -62,8 +64,9 @@ public interface HandlerMapping {
|
|||
String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";
|
||||
|
||||
/**
|
||||
* Name of the {@link ServerWebExchange} attribute that contains a map with
|
||||
* URI matrix variables.
|
||||
* Name of the {@link ServerWebExchange#getAttributes() attribute} that
|
||||
* contains a map with URI variable names and a corresponding MultiValueMap
|
||||
* of URI matrix variables for each.
|
||||
* <p>Note: This attribute is not required to be supported by all
|
||||
* HandlerMapping implementations and may also not be present depending on
|
||||
* whether the HandlerMapping is configured to keep matrix variable content
|
||||
|
@ -72,8 +75,8 @@ public interface HandlerMapping {
|
|||
String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";
|
||||
|
||||
/**
|
||||
* Name of the {@link ServerWebExchange} attribute that contains the set of
|
||||
* producible MediaTypes applicable to the mapped handler.
|
||||
* Name of the {@link ServerWebExchange#getAttributes() attribute} containing
|
||||
* the set of producible MediaType's applicable to the mapped handler.
|
||||
* <p>Note: This attribute is not required to be supported by all
|
||||
* HandlerMapping implementations. Handlers should not necessarily expect
|
||||
* this request attribute to be present in all scenarios.
|
||||
|
|
|
@ -145,8 +145,9 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
|||
|
||||
validateHandler(handler, exchange);
|
||||
|
||||
exchange.getAttributes().put(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathWithinMapping);
|
||||
exchange.getAttributes().put(BEST_MATCHING_HANDLER_ATTRIBUTE, handler);
|
||||
exchange.getAttributes().put(BEST_MATCHING_PATTERN_ATTRIBUTE, bestMatch);
|
||||
exchange.getAttributes().put(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathWithinMapping);
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
|
|
@ -322,7 +322,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
|
|||
lookupPath + "': {" + m1 + ", " + m2 + "}");
|
||||
}
|
||||
}
|
||||
handleMatch(bestMatch.mapping, lookupPath, exchange);
|
||||
handleMatch(bestMatch.mapping, bestMatch.handlerMethod, lookupPath, exchange);
|
||||
return bestMatch.handlerMethod;
|
||||
}
|
||||
else {
|
||||
|
@ -342,10 +342,12 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
|
|||
/**
|
||||
* Invoked when a matching mapping is found.
|
||||
* @param mapping the matching mapping
|
||||
* @param handlerMethod the matching method
|
||||
* @param lookupPath the lookup path within the current mapping
|
||||
* @param exchange the current exchange
|
||||
*/
|
||||
protected void handleMatch(T mapping, String lookupPath, ServerWebExchange exchange) {
|
||||
protected void handleMatch(T mapping, HandlerMethod handlerMethod, String lookupPath,
|
||||
ServerWebExchange exchange) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -106,8 +106,10 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
|||
* @see HandlerMapping#PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE
|
||||
*/
|
||||
@Override
|
||||
protected void handleMatch(RequestMappingInfo info, String lookupPath, ServerWebExchange exchange) {
|
||||
super.handleMatch(info, lookupPath, exchange);
|
||||
protected void handleMatch(RequestMappingInfo info, HandlerMethod handlerMethod, String lookupPath,
|
||||
ServerWebExchange exchange) {
|
||||
|
||||
super.handleMatch(info, handlerMethod, lookupPath, exchange);
|
||||
|
||||
PathPattern bestPattern;
|
||||
Map<String, String> uriVariables;
|
||||
|
@ -133,6 +135,7 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
|||
));
|
||||
}
|
||||
|
||||
exchange.getAttributes().put(BEST_MATCHING_HANDLER_ATTRIBUTE, handlerMethod);
|
||||
exchange.getAttributes().put(BEST_MATCHING_PATTERN_ATTRIBUTE, bestPattern);
|
||||
exchange.getAttributes().put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriVariables);
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.springframework.http.HttpMethod;
|
|||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
|
@ -60,6 +61,7 @@ import static org.hamcrest.CoreMatchers.containsString;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.get;
|
||||
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.method;
|
||||
|
@ -69,6 +71,8 @@ import static org.springframework.web.bind.annotation.RequestMethod.OPTIONS;
|
|||
import static org.springframework.web.method.MvcAnnotationPredicates.getMapping;
|
||||
import static org.springframework.web.method.MvcAnnotationPredicates.requestMapping;
|
||||
import static org.springframework.web.method.ResolvableMethod.on;
|
||||
import static org.springframework.web.reactive.HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE;
|
||||
import static org.springframework.web.reactive.HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE;
|
||||
import static org.springframework.web.reactive.result.method.RequestMappingInfo.paths;
|
||||
|
||||
/**
|
||||
|
@ -77,6 +81,9 @@ import static org.springframework.web.reactive.result.method.RequestMappingInfo.
|
|||
*/
|
||||
public class RequestMappingInfoHandlerMappingTests {
|
||||
|
||||
private static final HandlerMethod handlerMethod = new HandlerMethod(new TestController(),
|
||||
ClassUtils.getMethod(TestController.class, "dummy"));
|
||||
|
||||
private TestRequestMappingInfoHandlerMapping handlerMapping;
|
||||
|
||||
|
||||
|
@ -169,8 +176,8 @@ public class RequestMappingInfoHandlerMappingTests {
|
|||
Mono<Object> mono = this.handlerMapping.getHandler(exchange);
|
||||
|
||||
assertError(mono, UnsupportedMediaTypeStatusException.class,
|
||||
ex -> assertEquals("Response status 415 with reason \"Invalid mime type \"bogus\": does not contain '/'\"",
|
||||
ex.getMessage()));
|
||||
ex -> assertEquals("Response status 415 with reason \"Invalid mime type \"bogus\": " +
|
||||
"does not contain '/'\"", ex.getMessage()));
|
||||
}
|
||||
|
||||
@Test // SPR-8462
|
||||
|
@ -219,7 +226,7 @@ public class RequestMappingInfoHandlerMappingTests {
|
|||
String lookupPath = exchange.getRequest().getPath().pathWithinApplication().value();
|
||||
|
||||
RequestMappingInfo key = paths("/{path1}/{path2}").build();
|
||||
this.handlerMapping.handleMatch(key, lookupPath, exchange);
|
||||
this.handlerMapping.handleMatch(key, handlerMethod, lookupPath, exchange);
|
||||
|
||||
String name = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
|
||||
Map<String, String> uriVariables = (Map<String, String>) exchange.getAttributes().get(name);
|
||||
|
@ -236,7 +243,7 @@ public class RequestMappingInfoHandlerMappingTests {
|
|||
ServerWebExchange exchange = method(HttpMethod.GET, url).toExchange();
|
||||
|
||||
String lookupPath = exchange.getRequest().getPath().pathWithinApplication().value();
|
||||
this.handlerMapping.handleMatch(key, lookupPath, exchange);
|
||||
this.handlerMapping.handleMatch(key, handlerMethod, lookupPath, exchange);
|
||||
|
||||
String name = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -252,11 +259,13 @@ public class RequestMappingInfoHandlerMappingTests {
|
|||
RequestMappingInfo key = paths("/{path1}/2", "/**").build();
|
||||
ServerWebExchange exchange = get("/1/2").toExchange();
|
||||
String lookupPath = exchange.getRequest().getPath().pathWithinApplication().value();
|
||||
this.handlerMapping.handleMatch(key, lookupPath, exchange);
|
||||
this.handlerMapping.handleMatch(key, handlerMethod, lookupPath, exchange);
|
||||
|
||||
PathPattern bestMatch = (PathPattern) exchange.getAttributes()
|
||||
.get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
|
||||
PathPattern bestMatch = (PathPattern) exchange.getAttributes().get(BEST_MATCHING_PATTERN_ATTRIBUTE);
|
||||
assertEquals("/{path1}/2", bestMatch.getPatternString());
|
||||
|
||||
HandlerMethod mapped = (HandlerMethod) exchange.getAttributes().get(BEST_MATCHING_HANDLER_ATTRIBUTE);
|
||||
assertSame(handlerMethod, mapped);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -264,10 +273,9 @@ public class RequestMappingInfoHandlerMappingTests {
|
|||
RequestMappingInfo key = paths().build();
|
||||
ServerWebExchange exchange = get("/1/2").toExchange();
|
||||
String lookupPath = exchange.getRequest().getPath().pathWithinApplication().value();
|
||||
this.handlerMapping.handleMatch(key, lookupPath, exchange);
|
||||
this.handlerMapping.handleMatch(key, handlerMethod, lookupPath, exchange);
|
||||
|
||||
PathPattern bestMatch = (PathPattern) exchange.getAttributes()
|
||||
.get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
|
||||
PathPattern bestMatch = (PathPattern) exchange.getAttributes().get(BEST_MATCHING_PATTERN_ATTRIBUTE);
|
||||
assertEquals("/1/2", bestMatch.getPatternString());
|
||||
}
|
||||
|
||||
|
@ -330,7 +338,6 @@ public class RequestMappingInfoHandlerMappingTests {
|
|||
.consumeErrorWith(error -> {
|
||||
assertEquals(exceptionClass, error.getClass());
|
||||
consumer.accept((T) error);
|
||||
|
||||
})
|
||||
.verify();
|
||||
}
|
||||
|
@ -375,19 +382,19 @@ public class RequestMappingInfoHandlerMappingTests {
|
|||
private void handleMatch(ServerWebExchange exchange, String pattern) {
|
||||
RequestMappingInfo info = paths(pattern).build();
|
||||
String lookupPath = exchange.getRequest().getPath().pathWithinApplication().value();
|
||||
this.handlerMapping.handleMatch(info, lookupPath, exchange);
|
||||
this.handlerMapping.handleMatch(info, handlerMethod, lookupPath, exchange);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private MultiValueMap<String, String> getMatrixVariables(ServerWebExchange exchange, String uriVarName) {
|
||||
String attrName = HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE;
|
||||
return ((Map<String, MultiValueMap<String, String>>) exchange.getAttributes().get(attrName)).get(uriVarName);
|
||||
return ((Map<String, MultiValueMap<String, String>>) exchange.getAttributes()
|
||||
.get(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE)).get(uriVarName);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, String> getUriTemplateVariables(ServerWebExchange exchange) {
|
||||
String attrName = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
|
||||
return (Map<String, String>) exchange.getAttributes().get(attrName);
|
||||
return (Map<String, String>) exchange.getAttributes()
|
||||
.get(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
}
|
||||
|
||||
|
||||
|
@ -446,6 +453,8 @@ public class RequestMappingInfoHandlerMappingTests {
|
|||
headers.add("Allow", "PUT,POST");
|
||||
return headers;
|
||||
}
|
||||
|
||||
public void dummy() { }
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -96,11 +96,11 @@ public interface HandlerMapping {
|
|||
|
||||
/**
|
||||
* Name of the {@link HttpServletRequest} attribute that contains a map with
|
||||
* URI matrix variables.
|
||||
* URI variable names and a corresponding MultiValueMap of URI matrix
|
||||
* variables for each.
|
||||
* <p>Note: This attribute is not required to be supported by all
|
||||
* HandlerMapping implementations and may also not be present depending on
|
||||
* whether the HandlerMapping is configured to keep matrix variable content
|
||||
* in the request URI.
|
||||
*/
|
||||
String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";
|
||||
|
||||
|
|
Loading…
Reference in New Issue