Add PathSegmentContainer subPath extracting method
This commit is contained in:
parent
1018bf771b
commit
97917aa57d
|
@ -19,6 +19,7 @@ import java.nio.charset.Charset;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
@ -56,7 +57,7 @@ class DefaultPathSegmentContainer implements PathSegmentContainer {
|
||||||
private final boolean trailingSlash;
|
private final boolean trailingSlash;
|
||||||
|
|
||||||
|
|
||||||
DefaultPathSegmentContainer(String path, List<PathSegment> segments) {
|
private DefaultPathSegmentContainer(String path, List<PathSegment> segments) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.absolute = path.startsWith("/");
|
this.absolute = path.startsWith("/");
|
||||||
this.pathSegments = Collections.unmodifiableList(segments);
|
this.pathSegments = Collections.unmodifiableList(segments);
|
||||||
|
@ -188,6 +189,21 @@ class DefaultPathSegmentContainer implements PathSegmentContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PathSegmentContainer subPath(PathSegmentContainer container, int fromIndex, int toIndex) {
|
||||||
|
List<PathSegment> segments = container.pathSegments();
|
||||||
|
if (fromIndex == 0 && toIndex == segments.size()) {
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
Assert.isTrue(fromIndex < toIndex, "fromIndex: " + fromIndex + " should be < toIndex " + toIndex);
|
||||||
|
Assert.isTrue(fromIndex >= 0 && fromIndex < segments.size(), "Invalid fromIndex: " + fromIndex);
|
||||||
|
Assert.isTrue(toIndex >= 0 && toIndex <= segments.size(), "Invalid toIndex: " + toIndex);
|
||||||
|
|
||||||
|
List<PathSegment> subList = segments.subList(fromIndex, toIndex);
|
||||||
|
String prefix = fromIndex > 0 || container.isAbsolute() ? "/" : "";
|
||||||
|
String suffix = toIndex == segments.size() && container.hasTrailingSlash() ? "/" : "";
|
||||||
|
String path = subList.stream().map(PathSegment::value).collect(Collectors.joining(prefix, "/", suffix));
|
||||||
|
return new DefaultPathSegmentContainer(path, subList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class DefaultPathSegment implements PathSegment {
|
private static class DefaultPathSegment implements PathSegment {
|
||||||
|
|
|
@ -17,7 +17,6 @@ package org.springframework.http.server.reactive;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
@ -41,16 +40,15 @@ class DefaultRequestPath implements RequestPath {
|
||||||
DefaultRequestPath(URI uri, String contextPath, Charset charset) {
|
DefaultRequestPath(URI uri, String contextPath, Charset charset) {
|
||||||
this.fullPath = PathSegmentContainer.parse(uri.getRawPath(), charset);
|
this.fullPath = PathSegmentContainer.parse(uri.getRawPath(), charset);
|
||||||
this.contextPath = initContextPath(this.fullPath, contextPath);
|
this.contextPath = initContextPath(this.fullPath, contextPath);
|
||||||
this.pathWithinApplication = initPathWithinApplication(this.fullPath, this.contextPath);
|
this.pathWithinApplication = extractPathWithinApplication(this.fullPath, this.contextPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultRequestPath(RequestPath requestPath, String contextPath) {
|
DefaultRequestPath(RequestPath requestPath, String contextPath) {
|
||||||
this.fullPath = requestPath;
|
this.fullPath = requestPath;
|
||||||
this.contextPath = initContextPath(this.fullPath, contextPath);
|
this.contextPath = initContextPath(this.fullPath, contextPath);
|
||||||
this.pathWithinApplication = initPathWithinApplication(this.fullPath, this.contextPath);
|
this.pathWithinApplication = extractPathWithinApplication(this.fullPath, this.contextPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static PathSegmentContainer initContextPath(PathSegmentContainer path, String contextPath) {
|
private static PathSegmentContainer initContextPath(PathSegmentContainer path, String contextPath) {
|
||||||
if (!StringUtils.hasText(contextPath) || "/".equals(contextPath)) {
|
if (!StringUtils.hasText(contextPath) || "/".equals(contextPath)) {
|
||||||
return DefaultPathSegmentContainer.EMPTY_PATH;
|
return DefaultPathSegmentContainer.EMPTY_PATH;
|
||||||
|
@ -62,14 +60,13 @@ class DefaultRequestPath implements RequestPath {
|
||||||
int length = contextPath.length();
|
int length = contextPath.length();
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
|
|
||||||
List<PathSegment> result = new ArrayList<>();
|
for (int i=0; i < path.pathSegments().size(); i++) {
|
||||||
for (PathSegment pathSegment : path.pathSegments()) {
|
PathSegment pathSegment = path.pathSegments().get(i);
|
||||||
result.add(pathSegment);
|
counter += 1; // for slash separators
|
||||||
counter += 1; // for '/' separators
|
|
||||||
counter += pathSegment.value().length();
|
counter += pathSegment.value().length();
|
||||||
counter += pathSegment.semicolonContent().length();
|
counter += pathSegment.semicolonContent().length();
|
||||||
if (length == counter) {
|
if (length == counter) {
|
||||||
return new DefaultPathSegmentContainer(contextPath, result);
|
return DefaultPathSegmentContainer.subPath(path, 0, i + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,13 +75,10 @@ class DefaultRequestPath implements RequestPath {
|
||||||
" given path='" + path.value() + "'");
|
" given path='" + path.value() + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PathSegmentContainer initPathWithinApplication(PathSegmentContainer path,
|
private static PathSegmentContainer extractPathWithinApplication(PathSegmentContainer fullPath,
|
||||||
PathSegmentContainer contextPath) {
|
PathSegmentContainer contextPath) {
|
||||||
|
|
||||||
String value = path.value().substring(contextPath.value().length());
|
return PathSegmentContainer.subPath(fullPath, contextPath.pathSegments().size());
|
||||||
List<PathSegment> pathSegments = new ArrayList<>(path.pathSegments());
|
|
||||||
pathSegments.removeAll(contextPath.pathSegments());
|
|
||||||
return new DefaultPathSegmentContainer(value, pathSegments);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -67,4 +67,14 @@ public interface PathSegmentContainer {
|
||||||
return DefaultPathSegmentContainer.parsePath(path, encoding);
|
return DefaultPathSegmentContainer.parsePath(path, encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract a sub-path starting at the given offset into the path segment list.
|
||||||
|
* @param path the path to extract from
|
||||||
|
* @param pathSegmentIndex the start index (inclusive)
|
||||||
|
* @return the sub-path
|
||||||
|
*/
|
||||||
|
static PathSegmentContainer subPath(PathSegmentContainer path, int pathSegmentIndex) {
|
||||||
|
return DefaultPathSegmentContainer.subPath(path, pathSegmentIndex, path.pathSegments().size());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.springframework.util.MultiValueMap;
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for {@link DefaultPathSegmentContainer}.
|
* Unit tests for {@link DefaultPathSegmentContainer}.
|
||||||
|
@ -121,4 +122,17 @@ public class DefaultPathSegmentContainerTests {
|
||||||
assertEquals("hasTrailingSlash: '" + input + "'", trailingSlash, path.hasTrailingSlash());
|
assertEquals("hasTrailingSlash: '" + input + "'", trailingSlash, path.hasTrailingSlash());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void subPath() throws Exception {
|
||||||
|
// basic
|
||||||
|
PathSegmentContainer path = PathSegmentContainer.parse("/a/b/c", UTF_8);
|
||||||
|
assertSame(path, PathSegmentContainer.subPath(path, 0));
|
||||||
|
assertEquals("/b/c", PathSegmentContainer.subPath(path, 1).value());
|
||||||
|
assertEquals("/c", PathSegmentContainer.subPath(path, 2).value());
|
||||||
|
|
||||||
|
// trailing slash
|
||||||
|
path = PathSegmentContainer.parse("/a/b/", UTF_8);
|
||||||
|
assertEquals("/b/", PathSegmentContainer.subPath(path, 1).value());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue