DATAREST-1294 - Expose effective repository lookup path as request attribute.
We now expose a partially resolved PathPattern to contain the explicit repository base path so that the subpaths can be grouped around the individual repositories exposed. Related ticket: spring-projects/spring-boot#14872
This commit is contained in:
@@ -50,6 +50,7 @@ import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
/**
|
||||
* {@link RequestMappingHandlerMapping} implementation that will only find a handler method if a
|
||||
@@ -63,6 +64,9 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
|
||||
*/
|
||||
public class RepositoryRestHandlerMapping extends BasePathAwareHandlerMapping {
|
||||
|
||||
private static final PathPatternParser PARSER = new PathPatternParser();
|
||||
static final String EFFECTIVE_LOOKUP_PATH_KEY = "EFFECTIVE_REPOSITORY_LOOKUP_PATH";
|
||||
|
||||
private final ResourceMappings mappings;
|
||||
private final RepositoryRestConfiguration configuration;
|
||||
private final Optional<Repositories> repositories;
|
||||
@@ -151,7 +155,15 @@ public class RepositoryRestHandlerMapping extends BasePathAwareHandlerMapping {
|
||||
return handlerMethod;
|
||||
}
|
||||
|
||||
return mappings.exportsTopLevelResourceFor(getRepositoryBasePath(repositoryLookupPath)) ? handlerMethod : null;
|
||||
String repositoryBasePath = getRepositoryBasePath(repositoryLookupPath);
|
||||
|
||||
if (!mappings.exportsTopLevelResourceFor(repositoryBasePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
exposeEffectiveLookupPathKey(handlerMethod, request, repositoryBasePath);
|
||||
|
||||
return handlerMethod;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -235,6 +247,26 @@ public class RepositoryRestHandlerMapping extends BasePathAwareHandlerMapping {
|
||||
return secondSlashIndex == -1 ? repositoryLookupPath : repositoryLookupPath.substring(0, secondSlashIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes the effective repository resource lookup path as request attribute via {@link #EFFECTIVE_LOOKUP_PATH_KEY},
|
||||
* i.e. {@code /people/search/\{search\}} instead of {@code /\{repository\}/search/\{search\}}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param request must not be {@literal null}.
|
||||
* @param repositoryBasePath must not be {@literal null}.
|
||||
*/
|
||||
private void exposeEffectiveLookupPathKey(HandlerMethod method, HttpServletRequest request,
|
||||
String repositoryBasePath) {
|
||||
|
||||
RequestMappingInfo mappingInfo = getMappingForMethod(method.getMethod(), method.getBeanType());
|
||||
String pattern = mappingInfo.getPatternsCondition() //
|
||||
.getMatchingCondition(request)//
|
||||
.getPatterns() //
|
||||
.iterator().next();
|
||||
|
||||
request.setAttribute(EFFECTIVE_LOOKUP_PATH_KEY, PARSER.parse(pattern.replace("/{repository}", repositoryBasePath)));
|
||||
}
|
||||
|
||||
/**
|
||||
* No-op {@link StringValueResolver} that returns the given {@link String} value as is.
|
||||
*
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.util.pattern.PathPattern;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link RepositoryRestHandlerMapping}.
|
||||
@@ -270,6 +271,22 @@ public class RepositoryRestHandlerMappingUnitTests {
|
||||
assertThat(mapping.isHandler(type)).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAREST-1294
|
||||
public void exposesEffectiveRepositoryLookupPathAsRequestAttribute() throws Exception {
|
||||
|
||||
when(mappings.exportsTopLevelResourceFor("/people")).thenReturn(true);
|
||||
|
||||
MockHttpServletRequest mockRequest = new MockHttpServletRequest("GET", "/people/search/findByLastnameLike");
|
||||
|
||||
handlerMapping.afterPropertiesSet();
|
||||
handlerMapping.lookupHandlerMethod("/people/search/findByLastnameLike", mockRequest);
|
||||
|
||||
assertThat(mockRequest.getAttribute(RepositoryRestHandlerMapping.EFFECTIVE_LOOKUP_PATH_KEY)) //
|
||||
.isInstanceOfSatisfying(PathPattern.class, it -> {
|
||||
assertThat(it.getPatternString()).isEqualTo("/people/search/{search}");
|
||||
});
|
||||
}
|
||||
|
||||
private static Class<?> createProxy(Object source) {
|
||||
|
||||
ProxyFactory factory = new ProxyFactory(source);
|
||||
|
||||
Reference in New Issue
Block a user