Skip to content

Commit b159f1f

Browse files
authored
Pass query params to API spec validator (#66)
* pass query params to api spec validation * return empty map instead of null from param extraction * replacing new HashMap with Collections.emptyMap * replacing if statement with tertiary op
1 parent 40b1ac3 commit b159f1f

File tree

4 files changed

+87
-0
lines changed

4 files changed

+87
-0
lines changed

webtau-open-api/src/main/java/com/twosigma/webtau/openapi/OpenApiSpecValidator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,12 @@
2424
import com.twosigma.webtau.console.ansi.Color;
2525
import com.twosigma.webtau.http.validation.HttpValidationResult;
2626

27+
import java.util.List;
28+
import java.util.Map;
2729
import java.util.Optional;
2830

2931
import static com.twosigma.webtau.http.HttpUrl.extractPath;
32+
import static com.twosigma.webtau.http.HttpUrl.extractQueryParams;
3033

3134
public class OpenApiSpecValidator {
3235
private final SwaggerRequestResponseValidator openApiValidator;
@@ -75,6 +78,8 @@ private SimpleRequest buildRequest(HttpValidationResult result) {
7578
result.getRequestHeader().forEachProperty(builder::withHeader);
7679
}
7780

81+
extractQueryParams(result.getFullUrl()).forEach(builder::withQueryParam);
82+
7883
return builder.build();
7984
}
8085
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.twosigma.webtau.http;
2+
3+
import java.util.Arrays;
4+
import java.util.List;
5+
import java.util.Map;
6+
import java.util.stream.Collectors;
7+
8+
public class HttpQueryParamsParser {
9+
public static Map<String, List<String>> parseQueryParams(String queryParams) {
10+
String[] params = queryParams.split("&");
11+
12+
return Arrays.stream(params)
13+
.map(p -> p.split("="))
14+
.collect(Collectors.groupingBy(HttpQueryParamsParser::extractQueryKey,
15+
Collectors.mapping(HttpQueryParamsParser::extractQueryValue, Collectors.toList())));
16+
}
17+
18+
private static String extractQueryKey(String[] splitParam) {
19+
String key = splitParam[0];
20+
21+
int openingBraceIdx = key.indexOf('[');
22+
if (openingBraceIdx >= 0 && key.contains("]")) {
23+
key = key.substring(0, openingBraceIdx);
24+
}
25+
26+
return key;
27+
}
28+
29+
private static String extractQueryValue(String[] splitParam) {
30+
return splitParam.length == 1 ? null : splitParam[1];
31+
}
32+
}

webtau-rest/src/main/java/com/twosigma/webtau/http/HttpUrl.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.net.MalformedURLException;
2020
import java.net.URL;
21+
import java.util.*;
2122

2223
public class HttpUrl {
2324
private HttpUrl() {
@@ -42,6 +43,31 @@ public static String extractPath(String url) {
4243
}
4344
}
4445

46+
public static Map<String, List<String>> extractQueryParams(String url) {
47+
String queryParams = isFull(url) ?
48+
extractQueryParamsFromFullUrl(url) :
49+
extractQueryParamsFromRelativeUrl(url);
50+
51+
return queryParams == null ? Collections.emptyMap() : HttpQueryParamsParser.parseQueryParams(queryParams);
52+
}
53+
54+
private static String extractQueryParamsFromRelativeUrl(String url) {
55+
int queryParamsStart = url.indexOf('?');
56+
if (queryParamsStart < 0) {
57+
return null;
58+
} else {
59+
return url.substring(queryParamsStart + 1);
60+
}
61+
}
62+
63+
private static String extractQueryParamsFromFullUrl(String url) {
64+
try {
65+
return new URL(url).getQuery();
66+
} catch (MalformedURLException e) {
67+
throw new IllegalArgumentException("invalid url: " + url, e);
68+
}
69+
}
70+
4571
public static String concat(String left, String right) {
4672
if (left == null) {
4773
throw new IllegalArgumentException("passed url on the left is NULL");

webtau-rest/src/test/groovy/com/twosigma/webtau/http/HttpUrlTest.groovy

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,28 @@ class HttpUrlTest {
6666
HttpUrl.extractPath('garbage://localhost:8080/relative/path').should == '/relative/path'
6767
} should throwException(IllegalArgumentException, 'invalid url: garbage://localhost:8080/relative/path')
6868
}
69+
70+
@Test
71+
void "extract query params from a given url"() {
72+
def expectedParams = [a: ['b'], c: ['d']]
73+
def expectedMultiParams = [a: ['b', 'c']]
74+
def expectedNullParams = [a: [null], b: ['c']]
75+
76+
HttpUrl.extractQueryParams('relative/path?a=b&c=d').should == expectedParams
77+
HttpUrl.extractQueryParams('https://localhost:8080/relative/path?a=b&c=d').should == expectedParams
78+
HttpUrl.extractQueryParams('https://localhost:8080/relative/path?a=b&a=c').should == expectedMultiParams
79+
HttpUrl.extractQueryParams('https://localhost:8080/relative/path?a[0]=b&a[1]=c').should == expectedMultiParams
80+
81+
HttpUrl.extractQueryParams('https://localhost:8080/relative/path?a&b=c').should == expectedNullParams
82+
83+
HttpUrl.extractQueryParams('relative/path').should == [:]
84+
HttpUrl.extractQueryParams('https://localhost:8080/relative/path').should == [:]
85+
}
86+
87+
@Test
88+
void "validates full url before before extracting query params"() {
89+
code {
90+
HttpUrl.extractQueryParams('garbage://localhost:8080/relative/path').should == '/relative/path'
91+
} should throwException(IllegalArgumentException, 'invalid url: garbage://localhost:8080/relative/path')
92+
}
6993
}

0 commit comments

Comments
 (0)