remove default domain, stricter security
This commit is contained in:
parent
a5393441ed
commit
a34c444aec
16 changed files with 161 additions and 127 deletions
|
@ -1,5 +1,5 @@
|
|||
group = org.xbib
|
||||
name = net
|
||||
version = 3.2.0
|
||||
version = 3.3.0
|
||||
|
||||
org.gradle.warning.mode = ALL
|
||||
|
|
|
@ -21,7 +21,7 @@ public class PathDecoder {
|
|||
String path = pos > 0 ? pathAndQuery.substring(0, pos) : pathAndQuery;
|
||||
this.query = pos > 0 ? pathAndQuery.substring(pos + 1) : null;
|
||||
this.path = PathNormalizer.normalize(path);
|
||||
this.params = Parameter.builder().enablePercentDecoding();
|
||||
this.params = Parameter.builder().domain(Parameter.Domain.PATH).enablePercentDecoding();
|
||||
if (query != null) {
|
||||
parse(query);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package org.xbib.net.path;
|
||||
|
||||
import org.xbib.net.Parameter;
|
||||
import org.xbib.net.ParameterException;
|
||||
|
||||
public interface PathResolver<T> {
|
||||
|
||||
void resolve(String method, String path, ResultListener<T> listener);
|
||||
void resolve(String method, String path, ResultListener<T> listener) throws ParameterException;
|
||||
|
||||
interface Builder<T> {
|
||||
|
||||
|
@ -25,7 +26,7 @@ public interface PathResolver<T> {
|
|||
@FunctionalInterface
|
||||
interface ResultListener<T> {
|
||||
|
||||
void onResult(Result<T> result);
|
||||
void onResult(Result<T> result) throws ParameterException;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,11 +50,11 @@ public class PathMatcher {
|
|||
}
|
||||
|
||||
public Parameter extractUriTemplateVariables(String pattern, String path) {
|
||||
ParameterBuilder queryParameters = Parameter.builder();
|
||||
if (!doMatch(pattern, path, true, queryParameters)) {
|
||||
ParameterBuilder uriParameters = Parameter.builder().domain(Parameter.Domain.PATH);
|
||||
if (!doMatch(pattern, path, true, uriParameters)) {
|
||||
throw new IllegalStateException("Pattern \"" + pattern + "\" is not a match for \"" + path + "\"");
|
||||
}
|
||||
return queryParameters.build();
|
||||
return uriParameters.build();
|
||||
}
|
||||
|
||||
public PathComparator getPatternComparator(String path) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.xbib.net.path.simple;
|
|||
|
||||
import org.xbib.net.Parameter;
|
||||
import org.xbib.net.ParameterBuilder;
|
||||
import org.xbib.net.ParameterException;
|
||||
import org.xbib.net.util.CharMatcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -53,7 +54,7 @@ public class PathResolver<T> implements org.xbib.net.path.PathResolver<T> {
|
|||
* @param resultListener result listener
|
||||
*/
|
||||
@Override
|
||||
public void resolve(String method, String path, ResultListener<T> resultListener) {
|
||||
public void resolve(String method, String path, ResultListener<T> resultListener) throws ParameterException {
|
||||
Objects.requireNonNull(method, "method");
|
||||
Objects.requireNonNull(path, "path");
|
||||
resolve(method, builder.pathMatcher.tokenize(path), 0, new ArrayList<>(), resultListener);
|
||||
|
@ -68,7 +69,7 @@ public class PathResolver<T> implements org.xbib.net.path.PathResolver<T> {
|
|||
List<String> pathSegments,
|
||||
int index,
|
||||
List<String> parameters,
|
||||
ResultListener<T> resultListener) {
|
||||
ResultListener<T> resultListener) throws ParameterException {
|
||||
if (index < pathSegments.size()) {
|
||||
String segment = pathSegments.get(index);
|
||||
PathResolver<T> child = children.get(segment);
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.logging.Level;
|
|||
import java.util.logging.Logger;
|
||||
import org.xbib.net.Parameter;
|
||||
import org.xbib.net.ParameterBuilder;
|
||||
import org.xbib.net.ParameterException;
|
||||
import org.xbib.net.PathNormalizer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -37,7 +38,7 @@ public class PathResolver<T> implements org.xbib.net.path.PathResolver<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void resolve(String method, String path, ResultListener<T> listener) {
|
||||
public void resolve(String method, String path, ResultListener<T> listener) throws ParameterException {
|
||||
Objects.requireNonNull(method, "method");
|
||||
Objects.requireNonNull(path, "path");
|
||||
List<PathSegment> pathSegments = PathMatcher.tokenize(PathNormalizer.normalize(path),
|
||||
|
@ -54,7 +55,7 @@ public class PathResolver<T> implements org.xbib.net.path.PathResolver<T> {
|
|||
private ParameterBuilder resolve(List<PathSegment> pathSegments,
|
||||
int index,
|
||||
ParameterBuilder parameterBuilder,
|
||||
ResultListener<T> listener) {
|
||||
ResultListener<T> listener) throws ParameterException {
|
||||
ParameterBuilder pb = parameterBuilder;
|
||||
if (index < pathSegments.size()) {
|
||||
PathSegment segment = pathSegments.get(index);
|
||||
|
|
|
@ -10,17 +10,17 @@ import static org.junit.jupiter.api.Assertions.assertNull;
|
|||
class PathDecoderTest {
|
||||
|
||||
@Test
|
||||
void testPlusSign() {
|
||||
void testPlusSign() throws Exception {
|
||||
PathDecoder decoder = new PathDecoder("/path?a=b+c", "d=e+f");
|
||||
assertEquals("[b c]", decoder.getParameter().getAll("a", Parameter.Domain.DEFAULT).toString());
|
||||
assertEquals("[e f]", decoder.getParameter().getAll("d", Parameter.Domain.DEFAULT).toString());
|
||||
assertEquals("[b c]", decoder.getParameter().getAll("a", Parameter.Domain.PATH).toString());
|
||||
assertEquals("[e f]", decoder.getParameter().getAll("d", Parameter.Domain.PATH).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSlash() {
|
||||
void testSlash() throws Exception {
|
||||
PathDecoder decoder = new PathDecoder("path/foo/bar/?a=b+c", "d=e+f");
|
||||
assertEquals("[b c]", decoder.getParameter().getAll("a", Parameter.Domain.DEFAULT).toString());
|
||||
assertEquals("[e f]", decoder.getParameter().getAll("d", Parameter.Domain.DEFAULT).toString());
|
||||
assertEquals("[b c]", decoder.getParameter().getAll("a", Parameter.Domain.PATH).toString());
|
||||
assertEquals("[e f]", decoder.getParameter().getAll("d", Parameter.Domain.PATH).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -30,23 +30,23 @@ class PathDecoderTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testSlashes() {
|
||||
void testSlashes() throws Exception {
|
||||
PathDecoder decoder = new PathDecoder("//path?a=b+c", "d=e+f");
|
||||
assertEquals("/path", decoder.path());
|
||||
assertEquals("[b c]", decoder.getParameter().getAll("a", Parameter.Domain.DEFAULT).toString());
|
||||
assertEquals("[e f]", decoder.getParameter().getAll("d", Parameter.Domain.DEFAULT).toString());
|
||||
assertEquals("[b c]", decoder.getParameter().getAll("a", Parameter.Domain.PATH).toString());
|
||||
assertEquals("[e f]", decoder.getParameter().getAll("d", Parameter.Domain.PATH).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPlusPercent() {
|
||||
void testPlusPercent() throws Exception {
|
||||
PathDecoder decoder = new PathDecoder("//path?a=b%2Bc", "d=e%2Bf");
|
||||
assertEquals("/path", decoder.path());
|
||||
assertEquals("[b+c]", decoder.getParameter().getAll("a", Parameter.Domain.DEFAULT).toString());
|
||||
assertEquals("[e+f]", decoder.getParameter().getAll("d", Parameter.Domain.DEFAULT).toString());
|
||||
assertEquals("[b+c]", decoder.getParameter().getAll("a", Parameter.Domain.PATH).toString());
|
||||
assertEquals("[e+f]", decoder.getParameter().getAll("d", Parameter.Domain.PATH).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void decodeURL() {
|
||||
void decodeURL() throws Exception {
|
||||
String requestURI = "/pdfconverter/index.gtpl?x-fl-key=20190035592&x-source=ftp://dummy@xbib.org/upload/20190035592/20190035592.pdf&x-fl-target=ftp://dummy@xbib.org/fl/download/20190035592/Fernleihe_Kopienlieferung_null_FB201900373_BLQDMT62_20190035592_20190035592.pdf&x-fl-copy=&x-fl-ack=https://xbib.org/ack/&x-fl-pages=1-";
|
||||
URL url = URL.builder().path(requestURI).build();
|
||||
assertNull(url.getHost());
|
||||
|
@ -59,7 +59,7 @@ class PathDecoderTest {
|
|||
}
|
||||
assertEquals("x-fl-key=20190035592&x-source=ftp://dummy@xbib.org/upload/20190035592/20190035592.pdf&x-fl-target=ftp://dummy@xbib.org/fl/download/20190035592/Fernleihe_Kopienlieferung_null_FB201900373_BLQDMT62_20190035592_20190035592.pdf&x-fl-copy=&x-fl-ack=https://xbib.org/ack/&x-fl-pages=1-", url.getDecodedQuery());
|
||||
assertEquals("[x-fl-key=20190035592, x-source=ftp://dummy@xbib.org/upload/20190035592/20190035592.pdf, x-fl-target=ftp://dummy@xbib.org/fl/download/20190035592/Fernleihe_Kopienlieferung_null_FB201900373_BLQDMT62_20190035592_20190035592.pdf, x-fl-copy=, x-fl-ack=https://xbib.org/ack/, x-fl-pages=1-]", decoder.getParameter().toString());
|
||||
url = URL.from(decoder.getParameter().getAll("x-fl-target", Parameter.Domain.DEFAULT).get(0).toString());
|
||||
url = URL.from(decoder.getParameter().getAll("x-fl-target", Parameter.Domain.PATH).get(0).toString());
|
||||
assertEquals("ftp://dummy@xbib.org/fl/download/20190035592/Fernleihe_Kopienlieferung_null_FB201900373_BLQDMT62_20190035592_20190035592.pdf", url.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -311,38 +311,38 @@ class PathMatcherTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void extractUriTemplateVariablesRegex() {
|
||||
void extractUriTemplateVariablesRegex() throws Exception {
|
||||
Parameter result = pathMatcher.extractUriTemplateVariables("{symbolicName:[\\w\\.]+}-{version:[\\w\\.]+}.jar",
|
||||
"com.example-1.0.0.jar");
|
||||
assertEquals("com.example", result.getAll("symbolicName", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("1.0.0", result.getAll("version", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("com.example", result.getAll("symbolicName", Parameter.Domain.PATH).get(0));
|
||||
assertEquals("1.0.0", result.getAll("version", Parameter.Domain.PATH).get(0));
|
||||
|
||||
result = pathMatcher.extractUriTemplateVariables("{symbolicName:[\\w\\.]+}-sources-{version:[\\w\\.]+}.jar",
|
||||
"com.example-sources-1.0.0.jar");
|
||||
assertEquals("com.example", result.getAll("symbolicName", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("1.0.0", result.getAll("version", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("com.example", result.getAll("symbolicName", Parameter.Domain.PATH).get(0));
|
||||
assertEquals("1.0.0", result.getAll("version", Parameter.Domain.PATH).get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
void extractUriTemplateVarsRegexQualifiers() {
|
||||
void extractUriTemplateVarsRegexQualifiers() throws Exception {
|
||||
Parameter result = pathMatcher.extractUriTemplateVariables(
|
||||
"{symbolicName:[\\p{L}\\.]+}-sources-{version:[\\p{N}\\.]+}.jar",
|
||||
"com.example-sources-1.0.0.jar");
|
||||
assertEquals("com.example", result.getAll("symbolicName", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("1.0.0", result.getAll("version", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("com.example", result.getAll("symbolicName", Parameter.Domain.PATH).get(0));
|
||||
assertEquals("1.0.0", result.getAll("version", Parameter.Domain.PATH).get(0));
|
||||
result = pathMatcher.extractUriTemplateVariables(
|
||||
"{symbolicName:[\\w\\.]+}-sources-{version:[\\d\\.]+}-{year:\\d{4}}{month:\\d{2}}{day:\\d{2}}.jar",
|
||||
"com.example-sources-1.0.0-20100220.jar");
|
||||
assertEquals("com.example", result.getAll("symbolicName", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("1.0.0", result.getAll("version", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("2010", result.getAll("year", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("02", result.getAll("month", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("20", result.getAll("day", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("com.example", result.getAll("symbolicName", Parameter.Domain.PATH).get(0));
|
||||
assertEquals("1.0.0", result.getAll("version", Parameter.Domain.PATH).get(0));
|
||||
assertEquals("2010", result.getAll("year", Parameter.Domain.PATH).get(0));
|
||||
assertEquals("02", result.getAll("month", Parameter.Domain.PATH).get(0));
|
||||
assertEquals("20", result.getAll("day", Parameter.Domain.PATH).get(0));
|
||||
result = pathMatcher.extractUriTemplateVariables(
|
||||
"{symbolicName:[\\p{L}\\.]+}-sources-{version:[\\p{N}\\.\\{\\}]+}.jar",
|
||||
"com.example-sources-1.0.0.{12}.jar");
|
||||
assertEquals("com.example", result.getAll("symbolicName", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("1.0.0.{12}", result.getAll("version", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("com.example", result.getAll("symbolicName", Parameter.Domain.PATH).get(0));
|
||||
assertEquals("1.0.0.{12}", result.getAll("version", Parameter.Domain.PATH).get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.xbib.net.path.simple;
|
|||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xbib.net.Parameter;
|
||||
import org.xbib.net.ParameterException;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
@ -18,7 +19,7 @@ import static org.junit.jupiter.api.Assertions.fail;
|
|||
class PathResolverTest {
|
||||
|
||||
@Test
|
||||
void simple() {
|
||||
void simple() throws ParameterException {
|
||||
PathResolver<Integer> pathResolver = PathResolver.<Integer>builder()
|
||||
.add("GET", "explorer", 1234)
|
||||
.build();
|
||||
|
@ -29,7 +30,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void name() {
|
||||
void name() throws ParameterException {
|
||||
PathResolver<Integer> pathResolver = PathResolver.<Integer>builder()
|
||||
.add("GET", "/static/{file}", 1234)
|
||||
.add("HEAD", "/static/{file}", 1234)
|
||||
|
@ -39,7 +40,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void glob() {
|
||||
void glob() throws ParameterException {
|
||||
PathResolver<Integer> trie = PathResolver.<Integer>builder()
|
||||
.add("GET", "/static/**", 1234)
|
||||
.build();
|
||||
|
@ -48,7 +49,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void sharedPrefix() {
|
||||
void sharedPrefix() throws ParameterException {
|
||||
PathResolver<Integer> trie = PathResolver.<Integer>builder()
|
||||
.add("GET", "discovery/v1/rest", 1234)
|
||||
.add("GET", "discovery/v2/rest", 4321)
|
||||
|
@ -61,7 +62,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void prefix() {
|
||||
void prefix() throws ParameterException {
|
||||
PathResolver<Integer> trie = PathResolver.<Integer>builder()
|
||||
.add("GET", "discovery", 1234)
|
||||
.add("GET", "discovery/v1", 4321)
|
||||
|
@ -72,7 +73,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void parameter() {
|
||||
void parameter() throws ParameterException {
|
||||
PathResolver<Integer> trie = PathResolver.<Integer>builder()
|
||||
.add("GET", "discovery/{version}/rest", 1234)
|
||||
.build();
|
||||
|
@ -81,7 +82,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void multipleParameters() {
|
||||
void multipleParameters() throws ParameterException {
|
||||
PathResolver<Integer> trie = PathResolver.<Integer>builder()
|
||||
.add("GET", "discovery/{discovery_version}/apis/{api}/{format}", 1234)
|
||||
.build();
|
||||
|
@ -90,7 +91,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void sharedParameterPrefix() {
|
||||
void sharedParameterPrefix() throws ParameterException {
|
||||
PathResolver<Integer> trie = PathResolver.<Integer>builder()
|
||||
.add("GET", "discovery/{version}/rest", 1234)
|
||||
.add("GET", "discovery/{version}/rpc", 4321)
|
||||
|
@ -102,7 +103,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testResolveParameterAfterLiteral() {
|
||||
void testResolveParameterAfterLiteral() throws ParameterException {
|
||||
PathResolver<Integer> trie = PathResolver.<Integer>builder()
|
||||
.add("GET", "{one}/three", 1234)
|
||||
.add("GET", "one/two", 4321)
|
||||
|
@ -112,7 +113,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testResolveBacktrack() {
|
||||
void testResolveBacktrack() throws ParameterException {
|
||||
PathResolver<Integer> trie = PathResolver.<Integer>builder()
|
||||
.add("GET", "{one}/{two}/three/{four}", 1234)
|
||||
.add("GET", "one/two/{three}/four", 4321)
|
||||
|
@ -122,7 +123,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void pathMethodsWithDifferentParameterNames() {
|
||||
void pathMethodsWithDifferentParameterNames() throws ParameterException {
|
||||
PathResolver<Integer> trie = PathResolver.<Integer>builder()
|
||||
.add("GET", "test/{one}", 1234)
|
||||
.add("PUT", "test/{two}", 4321)
|
||||
|
@ -142,7 +143,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void laxDuplicatePath() {
|
||||
void laxDuplicatePath() throws ParameterException {
|
||||
PathResolver<Integer> pathResolver = PathResolver.<Integer>builder(false)
|
||||
.add("GET", "test/{one}", 1234)
|
||||
.add("GET", "test/{two}", 4321)
|
||||
|
@ -186,6 +187,8 @@ class PathResolverTest {
|
|||
fail("expected NullPointerException");
|
||||
} catch (NullPointerException e) {
|
||||
// expected
|
||||
} catch (ParameterException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,7 +226,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testFallback() {
|
||||
void testFallback() throws ParameterException {
|
||||
AtomicInteger counter = new AtomicInteger(0);
|
||||
org.xbib.net.path.PathResolver<Integer> trie = PathResolver.<Integer>builder()
|
||||
.add("GET", "/test/{one}", 1)
|
||||
|
@ -247,16 +250,16 @@ class PathResolverTest {
|
|||
}
|
||||
}
|
||||
|
||||
private void assertSuccessfulGetResolution(PathResolver<Integer> trie, String path, Integer value) {
|
||||
private void assertSuccessfulGetResolution(PathResolver<Integer> trie, String path, Integer value) throws ParameterException {
|
||||
assertSuccessfulResolution(trie, "GET", path, value);
|
||||
}
|
||||
|
||||
private void assertSuccessfulResolution(PathResolver<Integer> trie, String method, String path, Integer value) {
|
||||
private void assertSuccessfulResolution(PathResolver<Integer> trie, String method, String path, Integer value) throws ParameterException {
|
||||
assertSuccessfulResolution(trie, method, path, Set.of(value), Collections.emptyMap());
|
||||
}
|
||||
|
||||
private void assertSuccessfulGetResolution(PathResolver<Integer> trie, String path, Integer value,
|
||||
Map<String, String> rawParameters) {
|
||||
Map<String, String> rawParameters) throws ParameterException {
|
||||
assertSuccessfulResolution(trie, "GET", path, Set.of(value), rawParameters);
|
||||
}
|
||||
|
||||
|
@ -264,18 +267,18 @@ class PathResolverTest {
|
|||
String method,
|
||||
String path,
|
||||
Set<Integer> values,
|
||||
Map<String, String> rawParameters) {
|
||||
Map<String, String> rawParameters) throws ParameterException {
|
||||
trie.resolve(method, path, result -> {
|
||||
assertTrue(values.contains(result.getValue()));
|
||||
//assertThat(result.getRawParameters(), is(rawParameters));
|
||||
});
|
||||
}
|
||||
|
||||
private void assertFailedGetResolution(PathResolver<Integer> trie, String path) {
|
||||
private void assertFailedGetResolution(PathResolver<Integer> trie, String path) throws ParameterException {
|
||||
assertFailedGetResolution(trie, "GET", path);
|
||||
}
|
||||
|
||||
private void assertFailedGetResolution(PathResolver<Integer> trie, String method, String path) {
|
||||
private void assertFailedGetResolution(PathResolver<Integer> trie, String method, String path) throws ParameterException {
|
||||
trie.resolve(method, path, r-> { fail(); });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.xbib.net.path.structure;
|
|||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xbib.net.Parameter;
|
||||
import org.xbib.net.ParameterException;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
@ -20,7 +21,7 @@ import static org.junit.jupiter.api.Assertions.fail;
|
|||
class PathResolverTest {
|
||||
|
||||
@Test
|
||||
void example() {
|
||||
void example() throws ParameterException {
|
||||
PathResolver<Integer> pathResolver = PathResolver.<Integer>builder()
|
||||
.add( "GET", "/static/{file}", 1234)
|
||||
.build();
|
||||
|
@ -29,7 +30,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void simple() {
|
||||
void simple() throws ParameterException {
|
||||
PathResolver<Integer> pathResolver = PathResolver.<Integer>builder()
|
||||
.add("GET", "explorer", 1234)
|
||||
.build();
|
||||
|
@ -39,7 +40,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void sharedPrefix() {
|
||||
void sharedPrefix() throws ParameterException {
|
||||
PathResolver<Integer> pathResolver = PathResolver.<Integer>builder()
|
||||
.add("GET", "discovery/v1/rest", 1234)
|
||||
.add("GET", "discovery/v2/rest", 4321)
|
||||
|
@ -52,7 +53,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void prefix() {
|
||||
void prefix() throws ParameterException {
|
||||
PathResolver<Integer> pathResolver = PathResolver.<Integer>builder()
|
||||
.add("GET", "discovery", 1234)
|
||||
.add("GET", "discovery/v1", 4321)
|
||||
|
@ -63,7 +64,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void parameter() {
|
||||
void parameter() throws ParameterException {
|
||||
PathResolver<Integer> pathResolver = PathResolver.<Integer>builder()
|
||||
.add("GET", "discovery/{version}/rest", 1234)
|
||||
.build();
|
||||
|
@ -72,7 +73,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void multipleParameters() {
|
||||
void multipleParameters() throws ParameterException {
|
||||
PathResolver<Integer> pathResolver = PathResolver.<Integer>builder()
|
||||
.add("GET", "discovery/{discovery_version}/apis/{api}/{format}", 1234)
|
||||
.build();
|
||||
|
@ -81,7 +82,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void sharedParameterPrefix() {
|
||||
void sharedParameterPrefix() throws ParameterException {
|
||||
PathResolver<Integer> pathResolver = PathResolver.<Integer>builder()
|
||||
.add("GET", "discovery/{version}/rest", 1234)
|
||||
.add("GET", "discovery/{version}/rpc", 4321)
|
||||
|
@ -97,7 +98,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testResolveParameterAfterLiteral() {
|
||||
void testResolveParameterAfterLiteral() throws ParameterException {
|
||||
PathResolver<Integer> pathResolver = PathResolver.<Integer>builder()
|
||||
.add("GET", "{one}/three", 1234)
|
||||
.add("GET", "one/two", 4321)
|
||||
|
@ -108,7 +109,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testResolveBacktrack() {
|
||||
void testResolveBacktrack() throws ParameterException {
|
||||
PathResolver<Integer> pathResolver = PathResolver.<Integer>builder()
|
||||
.add("GET", "{one}/{two}/three/{four}", 1234)
|
||||
.add("GET", "one/two/{three}/four", 4321)
|
||||
|
@ -128,7 +129,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void pathMethodsWithDifferentParameterNames() {
|
||||
void pathMethodsWithDifferentParameterNames() throws ParameterException {
|
||||
PathResolver<Integer> pathResolver = PathResolver.<Integer>builder()
|
||||
.add("GET", "test/{one}", 1234)
|
||||
.add("GET", "test/{two}", 4321)
|
||||
|
@ -148,7 +149,7 @@ class PathResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void duplicatePathParams() {
|
||||
void duplicatePathParams() throws ParameterException {
|
||||
PathResolver<Integer> pathResolver = PathResolver.<Integer>builder()
|
||||
.add("GET", "test/{one}", 1234)
|
||||
.add("GET", "test/{two}", 4321)
|
||||
|
@ -197,11 +198,13 @@ class PathResolverTest {
|
|||
fail("expected NullPointerException");
|
||||
} catch (NullPointerException e) {
|
||||
// expected
|
||||
} catch (ParameterException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFallback() {
|
||||
void testFallback() throws ParameterException {
|
||||
AtomicInteger counter = new AtomicInteger(0);
|
||||
PathResolver<Integer> trie = PathResolver.<Integer>builder()
|
||||
.add( "GET", "/test/{one}", 1)
|
||||
|
@ -216,7 +219,7 @@ class PathResolverTest {
|
|||
|
||||
@Disabled
|
||||
@Test
|
||||
void testSuffixCatchAll() {
|
||||
void testSuffixCatchAll() throws ParameterException {
|
||||
AtomicInteger counter = new AtomicInteger(0);
|
||||
PathResolver<Integer> trie = PathResolver.<Integer>builder()
|
||||
.add( "GET", "/**/*.test", 1)
|
||||
|
@ -229,12 +232,12 @@ class PathResolverTest {
|
|||
assertThat(counter.get(), equalTo(2));
|
||||
}
|
||||
|
||||
private void assertSuccessfulResolution(PathResolver<Integer> pathResolver, String path, Integer value) {
|
||||
private void assertSuccessfulResolution(PathResolver<Integer> pathResolver, String path, Integer value) throws ParameterException {
|
||||
assertSuccessfulResolution(pathResolver, "GET", path, value, Parameter.builder().domain(Parameter.Domain.PATH).build());
|
||||
}
|
||||
|
||||
private void assertSuccessfulResolution(PathResolver<Integer> pathResolver, String method, String path, Integer value,
|
||||
Parameter parameter) {
|
||||
Parameter parameter) throws ParameterException {
|
||||
AtomicBoolean found = new AtomicBoolean(false);
|
||||
pathResolver.resolve(method, path, result -> {
|
||||
assertThat(result, notNullValue());
|
||||
|
@ -246,7 +249,7 @@ class PathResolverTest {
|
|||
assertTrue(found.get());
|
||||
}
|
||||
|
||||
private void assertFailedGetResolution(PathResolver<Integer> pathResolver, String path) {
|
||||
private void assertFailedGetResolution(PathResolver<Integer> pathResolver, String path) throws ParameterException {
|
||||
pathResolver.resolve("GET", path, r -> assertThat(r, nullValue()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import org.xbib.datastructures.common.Pair;
|
|||
public class Parameter implements Iterable<Pair<String, Object>>, Comparable<Parameter> {
|
||||
|
||||
public enum Domain {
|
||||
DEFAULT,
|
||||
UNDEFINED,
|
||||
QUERY,
|
||||
FORM,
|
||||
PATH,
|
||||
|
@ -92,7 +92,7 @@ public class Parameter implements Iterable<Pair<String, Object>>, Comparable<Par
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public String getAsString(String key, Domain domain) {
|
||||
public String getAsString(String key, Domain domain) throws ParameterException {
|
||||
Object object = get(key, domain);
|
||||
if (object instanceof Collection) {
|
||||
Collection<Object> collection = (Collection<Object>) object;
|
||||
|
@ -108,7 +108,7 @@ public class Parameter implements Iterable<Pair<String, Object>>, Comparable<Par
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Integer getAsInteger(String key, Domain domain) {
|
||||
public Integer getAsInteger(String key, Domain domain) throws ParameterException {
|
||||
Object object = get(key, domain);
|
||||
if (object instanceof Collection) {
|
||||
Collection<Object> collection = (Collection<Object>) object;
|
||||
|
@ -128,7 +128,7 @@ public class Parameter implements Iterable<Pair<String, Object>>, Comparable<Par
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Boolean getAsBoolean(String key, Domain domain) {
|
||||
public Boolean getAsBoolean(String key, Domain domain) throws ParameterException {
|
||||
Object object = get(key, domain);
|
||||
if (object instanceof Collection) {
|
||||
Collection<Object> collection = (Collection<Object>) object;
|
||||
|
@ -147,49 +147,35 @@ public class Parameter implements Iterable<Pair<String, Object>>, Comparable<Par
|
|||
}
|
||||
}
|
||||
|
||||
public String allToString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(list.toString());
|
||||
builder.parameterMap.forEach((key, value) -> sb.append(" ").append(key).append(" -> ").append(value));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean hasElements() {
|
||||
return !list.isEmpty();
|
||||
}
|
||||
|
||||
public MultiMap<String, Object> asMultiMap() {
|
||||
public MultiMap<String, Object> asMultiMap() throws ParameterException{
|
||||
if (getDomain() == Domain.UNDEFINED) {
|
||||
throw new ParameterException("undefined domain");
|
||||
}
|
||||
MultiMap<String, Object> multiMap = new LinkedHashSetMultiMap<>();
|
||||
this.forEach(p -> multiMap.put(p.getKey(), p.getValue()));
|
||||
return multiMap;
|
||||
}
|
||||
|
||||
public Map<String, Object> asSingleValuedMap() {
|
||||
public Map<String, Object> asSingleValuedMap() throws ParameterException {
|
||||
if (getDomain() == Domain.UNDEFINED) {
|
||||
throw new ParameterException("undefined domain");
|
||||
}
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
this.forEach(p -> map.put(p.getKey(), createValue(p.getValue())));
|
||||
return map;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Object createValue(Object object) {
|
||||
if (object instanceof Collection) {
|
||||
Collection<Object> collection = (Collection<Object>) object;
|
||||
if (collection.size() == 1) {
|
||||
return collection.iterator().next();
|
||||
} else {
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
public List<Object> getAllDomain(Domain domain) {
|
||||
public List<Object> getAllInDomain(Domain domain) {
|
||||
Parameter parameter = null;
|
||||
if (builder.parameterMap.containsKey(domain)) {
|
||||
parameter = builder.parameterMap.get(domain);
|
||||
}
|
||||
if (parameter != null) {
|
||||
return parameter.getAllDomain(domain);
|
||||
return parameter.getAllInDomain(domain);
|
||||
}
|
||||
if (getDomain().equals(domain)) {
|
||||
return list.stream()
|
||||
|
@ -213,7 +199,10 @@ public class Parameter implements Iterable<Pair<String, Object>>, Comparable<Par
|
|||
return false;
|
||||
}
|
||||
|
||||
public Parameter getDomain(Domain domain) {
|
||||
public Parameter get(Domain domain) throws ParameterException {
|
||||
if (getDomain() == Domain.UNDEFINED) {
|
||||
throw new ParameterException("undefined domain");
|
||||
}
|
||||
if (builder.parameterMap.containsKey(domain)) {
|
||||
return builder.parameterMap.get(domain);
|
||||
}
|
||||
|
@ -223,7 +212,10 @@ public class Parameter implements Iterable<Pair<String, Object>>, Comparable<Par
|
|||
return null;
|
||||
}
|
||||
|
||||
public List<Object> getAll(String key, Domain domain) {
|
||||
public List<Object> getAll(String key, Domain domain) throws Exception {
|
||||
if (getDomain() == Domain.UNDEFINED) {
|
||||
throw new ParameterException("undefined domain");
|
||||
}
|
||||
Parameter parameter = null;
|
||||
if (builder.parameterMap.containsKey(domain)) {
|
||||
parameter = builder.parameterMap.get(domain);
|
||||
|
@ -255,7 +247,10 @@ public class Parameter implements Iterable<Pair<String, Object>>, Comparable<Par
|
|||
return false;
|
||||
}
|
||||
|
||||
public Object get(String key, Domain domain) {
|
||||
public Object get(String key, Domain domain) throws ParameterException {
|
||||
if (getDomain() == Domain.UNDEFINED) {
|
||||
throw new ParameterException("undefined domain");
|
||||
}
|
||||
Parameter parameter = null;
|
||||
if (builder.parameterMap.containsKey(domain)) {
|
||||
parameter = builder.parameterMap.get(domain);
|
||||
|
@ -278,4 +273,24 @@ public class Parameter implements Iterable<Pair<String, Object>>, Comparable<Par
|
|||
public String getAsQueryString() {
|
||||
return queryString;
|
||||
}
|
||||
|
||||
private String allToString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(list.toString());
|
||||
builder.parameterMap.forEach((key, value) -> sb.append(" ").append(key).append(" -> ").append(value));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Object createValue(Object object) {
|
||||
if (object instanceof Collection) {
|
||||
Collection<Object> collection = (Collection<Object>) object;
|
||||
if (collection.size() == 1) {
|
||||
return collection.iterator().next();
|
||||
} else {
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ public class ParameterBuilder implements PairValidator {
|
|||
ParameterBuilder() {
|
||||
this.list = new ArrayList<>();
|
||||
this.parameterMap = new HashMap<>();
|
||||
this.domain = Parameter.Domain.DEFAULT;
|
||||
this.domain = Parameter.Domain.UNDEFINED;
|
||||
this.limit = 0;
|
||||
}
|
||||
|
||||
|
|
9
net/src/main/java/org/xbib/net/ParameterException.java
Normal file
9
net/src/main/java/org/xbib/net/ParameterException.java
Normal file
|
@ -0,0 +1,9 @@
|
|||
package org.xbib.net;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class ParameterException extends Exception {
|
||||
|
||||
public ParameterException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -82,7 +82,7 @@ public class URLBuilder {
|
|||
.onMalformedInput(codingErrorAction)
|
||||
.onUnmappableCharacter(codingErrorAction);
|
||||
this.percentDecoder = new PercentDecoder(charsetDecoder);
|
||||
this.queryParams = Parameter.builder();
|
||||
this.queryParams = Parameter.builder().domain(Parameter.Domain.QUERY);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -301,7 +301,6 @@ public class URLBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A path segment with associated matrix params, if any.
|
||||
*/
|
||||
|
|
|
@ -17,33 +17,35 @@ public class ParameterTest {
|
|||
public void testEmptyBuilder() {
|
||||
Parameter parameter = Parameter.builder().build();
|
||||
assertNotNull(parameter);
|
||||
assertFalse(parameter.containsKey("param1", Parameter.Domain.DEFAULT));
|
||||
assertFalse(parameter.containsKey("param1", Parameter.Domain.UNDEFINED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleParameter() {
|
||||
Parameter parameter = Parameter.builder()
|
||||
.domain(Parameter.Domain.QUERY)
|
||||
.add("Hello", "World")
|
||||
.build();
|
||||
assertNotNull(parameter);
|
||||
assertTrue(parameter.containsKey("Hello", Parameter.Domain.DEFAULT));
|
||||
assertTrue(parameter.containsKey("Hello", Parameter.Domain.QUERY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDuplicateParameter() {
|
||||
public void testDuplicateParameter() throws Exception {
|
||||
Parameter parameter = Parameter.builder()
|
||||
.domain(Parameter.Domain.QUERY)
|
||||
.enableDuplicates()
|
||||
.add("Hello", "World")
|
||||
.add("Hello", "World")
|
||||
.add("Hello", "World")
|
||||
.build();
|
||||
assertNotNull(parameter);
|
||||
assertTrue(parameter.containsKey("Hello", Parameter.Domain.DEFAULT));
|
||||
assertEquals(List.of("World", "World", "World"), parameter.getAll("Hello", Parameter.Domain.DEFAULT));
|
||||
assertTrue(parameter.containsKey("Hello", Parameter.Domain.QUERY));
|
||||
assertEquals(List.of("World", "World", "World"), parameter.getAll("Hello", Parameter.Domain.QUERY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHttpHeaderParameter() {
|
||||
public void testHttpHeaderParameter() throws Exception {
|
||||
Parameter parameter = Parameter.builder()
|
||||
.charset(StandardCharsets.US_ASCII)
|
||||
.lowercase()
|
||||
|
@ -116,20 +118,20 @@ public class ParameterTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testSimpleParse() {
|
||||
ParameterBuilder queryParameters = Parameter.builder();
|
||||
void testSimpleParse() throws Exception {
|
||||
ParameterBuilder queryParameters = Parameter.builder().domain(Parameter.Domain.QUERY);
|
||||
String body = "a=b&c=d&e=f";
|
||||
queryParameters.addPercentEncodedBody(body);
|
||||
Parameter parameter = queryParameters.build();
|
||||
assertEquals("b", parameter.getAll("a", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("d", parameter.getAll("c", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("f", parameter.getAll("e", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("b", parameter.getAll("a", Parameter.Domain.QUERY).get(0));
|
||||
assertEquals("d", parameter.getAll("c", Parameter.Domain.QUERY).get(0));
|
||||
assertEquals("f", parameter.getAll("e", Parameter.Domain.QUERY).get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseExceedingParamLimit() {
|
||||
Assertions.assertThrows(IllegalArgumentException.class, () -> {
|
||||
ParameterBuilder queryParameters = Parameter.builder().limit(100);
|
||||
ParameterBuilder queryParameters = Parameter.builder().domain(Parameter.Domain.QUERY).limit(100);
|
||||
List<String> list = new ArrayList<>();
|
||||
for (int i = 0; i < 200; i++) {
|
||||
list.add("a" + i + "=b" + i);
|
||||
|
@ -137,18 +139,19 @@ public class ParameterTest {
|
|||
String body = String.join("&", list);
|
||||
queryParameters.addPercentEncodedBody(body);
|
||||
Parameter parameter = queryParameters.build();
|
||||
assertEquals("b0", parameter.getAll("a0", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("b99", parameter.getAll("a99", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("[]", parameter.getAll("a100", Parameter.Domain.DEFAULT).toString());
|
||||
assertEquals("b0", parameter.getAll("a0", Parameter.Domain.QUERY).get(0));
|
||||
assertEquals("b99", parameter.getAll("a99", Parameter.Domain.QUERY).get(0));
|
||||
assertEquals("[]", parameter.getAll("a100", Parameter.Domain.QUERY).toString());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDomains() {
|
||||
void testDomains() throws ParameterException {
|
||||
Parameter p1 = Parameter.builder().domain(Parameter.Domain.QUERY).add("a", "a").build();
|
||||
Parameter p2 = Parameter.builder().domain(Parameter.Domain.FORM).add("b", "b").build();
|
||||
Parameter p3 = Parameter.builder().domain(Parameter.Domain.HEADER).add("c", "c").build();
|
||||
Parameter p = Parameter.builder()
|
||||
.domain(Parameter.Domain.QUERY)
|
||||
.add(p1)
|
||||
.add(p2)
|
||||
.add(p3)
|
||||
|
@ -162,6 +165,5 @@ public class ParameterTest {
|
|||
assertTrue(p.isPresent(Parameter.Domain.QUERY));
|
||||
assertTrue(p.isPresent(Parameter.Domain.FORM));
|
||||
assertTrue(p.isPresent(Parameter.Domain.HEADER));
|
||||
assertFalse(p.isPresent(Parameter.Domain.DEFAULT));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -327,7 +327,7 @@ class URLParserTest {
|
|||
assertEquals("path", pathSegment.getSegment());
|
||||
assertEquals("p2", pathSegment.getMatrixParams().get(0).getKey());
|
||||
assertEquals("v2", pathSegment.getMatrixParams().get(0).getValue());
|
||||
assertEquals("v3", url.getQueryParams().getAll("q1", Parameter.Domain.DEFAULT).get(0));
|
||||
assertEquals("v3", url.getQueryParams().getAll("q1", Parameter.Domain.QUERY).get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in a new issue