mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-17 16:39:29 +00:00
PathApiVersionResolver is not nullable
Closes gh-35265
This commit is contained in:
@@ -49,6 +49,11 @@ This strategy resolves the API version from a request. The WebFlux config provid
|
||||
options to resolve from a header, query parameter, media type parameter,
|
||||
or from the URL path. You can also use a custom `ApiVersionResolver`.
|
||||
|
||||
NOTE: The path resolver always resolves the version from the specified path segment, or
|
||||
raises `InvalidApiVersionException` otherwise, and therefore it cannot yield to other
|
||||
resolvers.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -49,6 +49,11 @@ This strategy resolves the API version from a request. The MVC config provides b
|
||||
options to resolve from a header, query parameter, media type parameter,
|
||||
or from the URL path. You can also use a custom `ApiVersionResolver`.
|
||||
|
||||
NOTE: The path resolver always resolves the version from the specified path segment, or
|
||||
raises `InvalidApiVersionException` otherwise, and therefore it cannot yield to other
|
||||
resolvers.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+15
-10
@@ -17,7 +17,6 @@
|
||||
package org.springframework.web.accept;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.http.server.PathContainer;
|
||||
import org.springframework.http.server.RequestPath;
|
||||
@@ -27,6 +26,11 @@ import org.springframework.web.util.ServletRequestPathUtils;
|
||||
/**
|
||||
* {@link ApiVersionResolver} that extract the version from a path segment.
|
||||
*
|
||||
* <p>Note that this resolver will either resolve the version from the specified
|
||||
* path segment, or raise an {@link InvalidApiVersionException}, e.g. if there
|
||||
* are not enough path segments. It never returns {@code null}, and therefore
|
||||
* cannot yield to other resolvers.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 7.0
|
||||
*/
|
||||
@@ -47,17 +51,18 @@ public class PathApiVersionResolver implements ApiVersionResolver {
|
||||
|
||||
|
||||
@Override
|
||||
public @Nullable String resolveVersion(HttpServletRequest request) {
|
||||
if (ServletRequestPathUtils.hasParsedRequestPath(request)) {
|
||||
RequestPath path = ServletRequestPathUtils.getParsedRequestPath(request);
|
||||
int i = 0;
|
||||
for (PathContainer.Element e : path.pathWithinApplication().elements()) {
|
||||
if (e instanceof PathContainer.PathSegment && i++ == this.pathSegmentIndex) {
|
||||
return e.value();
|
||||
}
|
||||
public String resolveVersion(HttpServletRequest request) {
|
||||
if (!ServletRequestPathUtils.hasParsedRequestPath(request)) {
|
||||
throw new IllegalStateException("Expected parsed request path");
|
||||
}
|
||||
RequestPath path = ServletRequestPathUtils.getParsedRequestPath(request);
|
||||
int i = 0;
|
||||
for (PathContainer.Element element : path.pathWithinApplication().elements()) {
|
||||
if (element instanceof PathContainer.PathSegment && i++ == this.pathSegmentIndex) {
|
||||
return element.value();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
throw new InvalidApiVersionException("No path segment at index " + this.pathSegmentIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
@@ -22,6 +22,7 @@ import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.util.ServletRequestPathUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PathApiVersionResolver}.
|
||||
@@ -35,6 +36,11 @@ public class PathApiVersionResolverTests {
|
||||
testResolve(1, "/app/1.1/path", "1.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void insufficientPathSegments() {
|
||||
assertThatThrownBy(() -> testResolve(0, "/", "1.0")).isInstanceOf(InvalidApiVersionException.class);
|
||||
}
|
||||
|
||||
private static void testResolve(int index, String requestUri, String expected) {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
|
||||
try {
|
||||
|
||||
+8
-4
@@ -16,15 +16,19 @@
|
||||
|
||||
package org.springframework.web.reactive.accept;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.http.server.PathContainer;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.accept.InvalidApiVersionException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* {@link ApiVersionResolver} that extract the version from a path segment.
|
||||
*
|
||||
* <p>Note that this resolver will either resolve the version from the specified
|
||||
* path segment, or raise an {@link InvalidApiVersionException}, e.g. if there
|
||||
* are not enough path segments. It never returns {@code null}, and therefore
|
||||
* cannot yield to other resolvers.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 7.0
|
||||
*/
|
||||
@@ -45,14 +49,14 @@ public class PathApiVersionResolver implements ApiVersionResolver {
|
||||
|
||||
|
||||
@Override
|
||||
public @Nullable String resolveVersion(ServerWebExchange exchange) {
|
||||
public String resolveVersion(ServerWebExchange exchange) {
|
||||
int i = 0;
|
||||
for (PathContainer.Element e : exchange.getRequest().getPath().pathWithinApplication().elements()) {
|
||||
if (e instanceof PathContainer.PathSegment && i++ == this.pathSegmentIndex) {
|
||||
return e.value();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
throw new InvalidApiVersionException("No path segment at index " + this.pathSegmentIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
-10
@@ -79,16 +79,6 @@ public class ApiVersionConfigurer {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a resolver that extracts the API version from a path segment.
|
||||
* @param index the index of the path segment to check; e.g. for URL's like
|
||||
* "/{version}/..." use index 0, for "/api/{version}/..." index 1.
|
||||
*/
|
||||
public ApiVersionConfigurer usePathSegment(int index) {
|
||||
this.versionResolvers.add(new PathApiVersionResolver(index));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add resolver to extract the version from a media type parameter found in
|
||||
* the Accept or Content-Type headers.
|
||||
@@ -101,6 +91,18 @@ public class ApiVersionConfigurer {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a resolver that extracts the API version from a path segment.
|
||||
* <p>Note that this resolver never returns {@code null}, and therefore
|
||||
* cannot yield to other resolvers, see {@link org.springframework.web.accept.PathApiVersionResolver}.
|
||||
* @param index the index of the path segment to check; e.g. for URL's like
|
||||
* "/{version}/..." use index 0, for "/api/{version}/..." index 1.
|
||||
*/
|
||||
public ApiVersionConfigurer usePathSegment(int index) {
|
||||
this.versionResolvers.add(new PathApiVersionResolver(index));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom resolvers to resolve the API version.
|
||||
* @param resolvers the resolvers to use
|
||||
|
||||
+7
@@ -18,11 +18,13 @@ package org.springframework.web.reactive.accept;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.web.accept.InvalidApiVersionException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.web.testfixture.server.MockServerWebExchange;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link org.springframework.web.accept.PathApiVersionResolver}.
|
||||
@@ -36,6 +38,11 @@ public class PathApiVersionResolverTests {
|
||||
testResolve(1, "/app/1.1/path", "1.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void insufficientPathSegments() {
|
||||
assertThatThrownBy(() -> testResolve(0, "/", "1.0")).isInstanceOf(InvalidApiVersionException.class);
|
||||
}
|
||||
|
||||
private static void testResolve(int index, String requestUri, String expected) {
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(requestUri));
|
||||
String actual = new PathApiVersionResolver(index).resolveVersion(exchange);
|
||||
|
||||
+12
-10
@@ -80,16 +80,6 @@ public class ApiVersionConfigurer {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add resolver to extract the version from a path segment.
|
||||
* @param index the index of the path segment to check; e.g. for URL's like
|
||||
* "/{version}/..." use index 0, for "/api/{version}/..." index 1.
|
||||
*/
|
||||
public ApiVersionConfigurer usePathSegment(int index) {
|
||||
this.versionResolvers.add(new PathApiVersionResolver(index));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add resolver to extract the version from a media type parameter found in
|
||||
* the Accept or Content-Type headers.
|
||||
@@ -102,6 +92,18 @@ public class ApiVersionConfigurer {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add resolver to extract the version from a path segment.
|
||||
* <p>Note that this resolver never returns {@code null}, and therefore
|
||||
* cannot yield to other resolvers, see {@link PathApiVersionResolver}.
|
||||
* @param index the index of the path segment to check; e.g. for URL's like
|
||||
* "/{version}/..." use index 0, for "/api/{version}/..." index 1.
|
||||
*/
|
||||
public ApiVersionConfigurer usePathSegment(int index) {
|
||||
this.versionResolvers.add(new PathApiVersionResolver(index));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom resolvers to resolve the API version.
|
||||
* @param resolvers the resolvers to use
|
||||
|
||||
Reference in New Issue
Block a user