explicit http url decoding support

This commit is contained in:
Jonathan Shook
2020-12-22 23:33:48 -06:00
parent f0223501f8
commit 9d5c225ca8
2 changed files with 83 additions and 65 deletions

View File

@@ -8,12 +8,13 @@ import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class HttpFormatParser { public class HttpFormatParser {
public static Map<String, String> parseUrl(String uri) { public static Map<String, String> parseUrl(String uri) {
if (uri.matches("http.+")) { if (uri.matches("http.+")) {
return Map.of("uri", rewriteUriWithStaticsEncoded(uri)); return Map.of("uri", rewriteExplicitSections(uri));
} }
return null; return null;
} }
@@ -54,7 +55,7 @@ public class HttpFormatParser {
throw new BasicError("Request template must have at least a method and a uri: " + methodAndHeaders[0]); throw new BasicError("Request template must have at least a method and a uri: " + methodAndHeaders[0]);
} }
props.put("method", methodLine[0]); props.put("method", methodLine[0]);
props.put("uri", rewriteUriWithStaticsEncoded(methodLine[1])); props.put("uri", rewriteExplicitSections(methodLine[1]));
if (methodLine.length == 3) { if (methodLine.length == 3) {
String actualVersion = methodLine[2]; String actualVersion = methodLine[2];
@@ -69,12 +70,26 @@ public class HttpFormatParser {
return props; return props;
} }
private static String rewriteUriWithStaticsEncoded(String template) { private final static Pattern DOENCODE = Pattern.compile("(URLENCODE|E)\\[\\[(?<data>.+?)\\]\\]");
String[] parts = template.split("\\?", 2);
private static String rewriteExplicitSections(String template) {
if (parts.length == 2) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String input = parts[1]; Matcher matcher = DOENCODE.matcher(template);
while (matcher.find()) {
String rewrite = matcher.group("data");
String encoded = rewriteStaticsOnly(rewrite);
matcher.appendReplacement(sb, encoded);
}
matcher.appendTail(sb);
return sb.toString();
}
private static String rewriteStaticsOnly(String template) {
StringBuilder sb = new StringBuilder();
String input = template;
Matcher matcher = ParsedTemplate.STANDARD_ANCHOR.matcher(input); Matcher matcher = ParsedTemplate.STANDARD_ANCHOR.matcher(input);
int idx = 0; int idx = 0;
while (matcher.find()) { while (matcher.find()) {
@@ -85,11 +100,7 @@ public class HttpFormatParser {
// matcher.appendReplacement(sb, "test-value" + idx); // matcher.appendReplacement(sb, "test-value" + idx);
} }
sb.append(URLEncoder.encode(input.substring(idx), StandardCharsets.UTF_8)); sb.append(URLEncoder.encode(input.substring(idx), StandardCharsets.UTF_8));
return parts[0] + "?" + sb.toString(); return sb.toString();
} else {
return template;
}
} }
} }

View File

@@ -120,12 +120,19 @@ All other request fields are optional and have reasonable defaults:
- **uri** - This is the URI that you might put into the URL bar of your - **uri** - This is the URI that you might put into the URL bar of your
browser. There is no default. browser. There is no default.
Example: `https://en.wikipedia.org/wiki/Leonhard_Euler` Example: `https://en.wikipedia.org/wiki/Leonhard_Euler`
If the uri contains a question mark '?' as a query delimiter, then all If the uri contains a question mark '?' as a query delimiter, then all
characters after this are automatically URL encoded. This is done for embedded sections which are contained within `URLENCODE[[` ... `]]`
any literal part of the uri. If you use bindings in the uri as sections are preprocessed by the HTTP driver. This allows you to keep
in `https://en.wikipedia.org/wiki/{topic}`, then it is up to you to your test data in a recognizable form. This is done at startup, so there
ensure that the values are produced in a valid form for a URI. You can is no cost during the test run. As an added convenience, binding points
use the `URLEncode()` binding function where needed to achieve this. which are within the encoded block will be preserved, so
both `https://en.wikipedia.org/URLENCODE[[wiki/]]{topic}` and
`https://en.wikipedia.org/URLENCODE[[wiki/{topic}]]` will yield the same
configuration. For a terser form, you can use `E[[...]]`. You must also
ensure that the values that are inserted at binding points are produced
in a valid form for a URI. You can use the `URLEncode()`
binding function where needed to achieve this.
- **method** - An optional request method. If not provided, "GET" is assumed. Any method name will - **method** - An optional request method. If not provided, "GET" is assumed. Any method name will
work here, even custom ones that are specific to a given target system. No validation is done for work here, even custom ones that are specific to a given target system. No validation is done for
standard method names, as there is no way to know what method names may be valid. standard method names, as there is no way to know what method names may be valid.
@@ -179,17 +186,16 @@ results. Support may be added for long-lived connections in a future release.
are those which do not redirect from HTTPS to HTTP. are those which do not redirect from HTTPS to HTTP.
- **diagnostics** - default: none - synonym: **diag** - **diagnostics** - default: none - synonym: **diag**
example: `diag=brief,1000` - print diagnostics for every 1000th example: `diag=brief,1000` - print diagnostics for every 1000th cycle,
cycle, including only brief details as explained below. including only brief details as explained below.
This setting is a selector for what level of verbosity you will get This setting is a selector for what level of verbosity you will get on
on the console. If you set this to true, you'll get every request the console. If you set this to true, you'll get every request and
and response logged to console. This is only for verifying that a test response logged to console. This is only for verifying that a test is
is configured and to spot check services before running higher scale configured and to spot check services before running higher scale tests.
tests.
All of the data shown in diagnostics is post-hoc, directly from All of the data shown in diagnostics is post-hoc, directly from the
the response provided by the internal HTTP client in the Java runtime. response provided by the internal HTTP client in the Java runtime.
If you want finer control over how much information diagnostics If you want finer control over how much information diagnostics
provides, you can specify a comma separated list of the below. provides, you can specify a comma separated list of the below.
@@ -201,10 +207,11 @@ results. Support may be added for long-lived connections in a future release.
this setting supersedes `data10` this setting supersedes `data10`
- data1000 - show only the first 1000 characters of each response body - data1000 - show only the first 1000 characters of each response body
this setting supersedes `data100` this setting supersedes `data100`
- data - show all of each response body - data - show all of each response body this setting
this setting supersedes `data1000` supersedes `data1000`
- redirects - show details for interstitial request which are made - redirects - show details for interstitial request which are made
when the client follows a redirect directive like a `location` header. when the client follows a redirect directive like a `location`
header.
- requests - show details for requests - requests - show details for requests
- responses - show details for responses - responses - show details for responses
- brief - Show headers, stats, requests, responses, and 10 characters - brief - Show headers, stats, requests, responses, and 10 characters
@@ -221,5 +228,5 @@ results. Support may be added for long-lived connections in a future release.
All of the diagnostic filters are incrementally added. All of the diagnostic filters are incrementally added.
- **timeout** - default: forever - - **timeout** - default: forever - Sets the timeout of each request in
Sets the timeout of each request in milliseconds. milliseconds.