mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-02-25 18:55:28 -06:00
nosqlbench-865 Apply urlencoder logic in http for all op field forms
This commit is contained in:
@@ -20,6 +20,8 @@ import io.nosqlbench.adapter.http.core.HttpFormatParser;
|
|||||||
import io.nosqlbench.adapter.http.core.HttpOp;
|
import io.nosqlbench.adapter.http.core.HttpOp;
|
||||||
import io.nosqlbench.adapter.http.core.HttpOpMapper;
|
import io.nosqlbench.adapter.http.core.HttpOpMapper;
|
||||||
import io.nosqlbench.adapter.http.core.HttpSpace;
|
import io.nosqlbench.adapter.http.core.HttpSpace;
|
||||||
|
import io.nosqlbench.api.config.standard.ConfigModel;
|
||||||
|
import io.nosqlbench.api.config.standard.Param;
|
||||||
import io.nosqlbench.engine.api.activityimpl.OpMapper;
|
import io.nosqlbench.engine.api.activityimpl.OpMapper;
|
||||||
import io.nosqlbench.engine.api.activityimpl.uniform.BaseDriverAdapter;
|
import io.nosqlbench.engine.api.activityimpl.uniform.BaseDriverAdapter;
|
||||||
import io.nosqlbench.engine.api.activityimpl.uniform.DriverAdapter;
|
import io.nosqlbench.engine.api.activityimpl.uniform.DriverAdapter;
|
||||||
@@ -68,6 +70,11 @@ public class HttpDriverAdapter extends BaseDriverAdapter<HttpOp, HttpSpace> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NBConfigModel getConfigModel() {
|
public NBConfigModel getConfigModel() {
|
||||||
return super.getConfigModel().add(HttpSpace.getConfigModel());
|
NBConfigModel thisCfgModel = ConfigModel.of(HttpDriverAdapter.class)
|
||||||
|
.add(Param.defaultTo("enable_urlencode", false)
|
||||||
|
.setDescription("Override auto-detection of URLENCODE[[ requirements in the uri field."))
|
||||||
|
.asReadOnly();
|
||||||
|
|
||||||
|
return super.getConfigModel().add(HttpSpace.getConfigModel()).add(thisCfgModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,12 +94,12 @@ public class HttpFormatParser {
|
|||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final static Pattern DOENCODE = Pattern.compile("(URLENCODE|E)\\[\\[(?<data>.+?)\\]\\]");
|
public final static Pattern URLENCODER_PATTERN = Pattern.compile("(URLENCODE|E)\\[\\[(?<data>.+?)\\]\\]");
|
||||||
|
|
||||||
public static String rewriteExplicitSections(String template) {
|
public static String rewriteExplicitSections(String template) {
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
Matcher matcher = DOENCODE.matcher(template);
|
Matcher matcher = URLENCODER_PATTERN.matcher(template);
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
String rewrite = matcher.group("data");
|
String rewrite = matcher.group("data");
|
||||||
String encoded = rewriteStaticsOnly(rewrite);
|
String encoded = rewriteStaticsOnly(rewrite);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import java.util.Optional;
|
|||||||
import java.util.function.LongFunction;
|
import java.util.function.LongFunction;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class HttpOpDispenser extends BaseOpDispenser<HttpOp,HttpSpace> {
|
public class HttpOpDispenser extends BaseOpDispenser<HttpOp, HttpSpace> {
|
||||||
|
|
||||||
private final LongFunction<HttpOp> opFunc;
|
private final LongFunction<HttpOp> opFunc;
|
||||||
public static final String DEFAULT_OK_BODY = ".+?";
|
public static final String DEFAULT_OK_BODY = ".+?";
|
||||||
@@ -63,9 +63,27 @@ public class HttpOpDispenser extends BaseOpDispenser<HttpOp,HttpSpace> {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
initBuilderF = op.enhanceFuncOptionally(initBuilderF, "uri", String.class, (b, v) -> b.uri(URI.create(v)));
|
Optional<LongFunction<String>> optionalUriFunc = op.getAsOptionalFunction("uri", String.class);
|
||||||
|
LongFunction<String> urifunc;
|
||||||
|
// Add support for URLENCODE on the uri field if either it statically or dynamically contains the E or URLENCODE pattern,
|
||||||
|
// OR the enable_urlencode op field is set to true.
|
||||||
|
if (optionalUriFunc.isPresent()) {
|
||||||
|
String testUriValue = optionalUriFunc.get().apply(0L);
|
||||||
|
if (HttpFormatParser.URLENCODER_PATTERN.matcher(testUriValue).find()
|
||||||
|
|| op.getStaticConfigOr("enable_urlencode", true)) {
|
||||||
|
initBuilderF =
|
||||||
|
op.enhanceFuncOptionally(
|
||||||
|
initBuilderF,
|
||||||
|
"uri",
|
||||||
|
String.class,
|
||||||
|
(b, v) -> b.uri(URI.create(HttpFormatParser.rewriteExplicitSections(v)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
initBuilderF = op.enhanceFuncOptionally(initBuilderF, "uri", String.class, (b, v) -> b.uri(URI.create(v)));
|
||||||
|
}
|
||||||
|
|
||||||
op.getOptionalStaticValue("follow_redirects",boolean.class);
|
op.getOptionalStaticValue("follow_redirects", boolean.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add header adders for any key provided in the op template which is capitalized
|
* Add header adders for any key provided in the op template which is capitalized
|
||||||
@@ -74,19 +92,19 @@ public class HttpOpDispenser extends BaseOpDispenser<HttpOp,HttpSpace> {
|
|||||||
.filter(n -> n.charAt(0) >= 'A')
|
.filter(n -> n.charAt(0) >= 'A')
|
||||||
.filter(n -> n.charAt(0) <= 'Z')
|
.filter(n -> n.charAt(0) <= 'Z')
|
||||||
.toList();
|
.toList();
|
||||||
if (headerNames.size()>0) {
|
if (headerNames.size() > 0) {
|
||||||
for (String headerName : headerNames) {
|
for (String headerName : headerNames) {
|
||||||
initBuilderF = op.enhanceFunc(initBuilderF,headerName,String.class, (b,h) -> b.header(headerName,h));
|
initBuilderF = op.enhanceFunc(initBuilderF, headerName, String.class, (b, h) -> b.header(headerName, h));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initBuilderF = op.enhanceFuncOptionally(initBuilderF,"timeout",long.class,(b,v) -> b.timeout(Duration.ofMillis(v)));
|
initBuilderF = op.enhanceFuncOptionally(initBuilderF, "timeout", long.class, (b, v) -> b.timeout(Duration.ofMillis(v)));
|
||||||
|
|
||||||
LongFunction<HttpRequest.Builder> finalInitBuilderF = initBuilderF;
|
LongFunction<HttpRequest.Builder> finalInitBuilderF = initBuilderF;
|
||||||
LongFunction<HttpRequest> reqF = l -> finalInitBuilderF.apply(l).build();
|
LongFunction<HttpRequest> reqF = l -> finalInitBuilderF.apply(l).build();
|
||||||
|
|
||||||
|
|
||||||
Pattern ok_status = op.getOptionalStaticValue("ok-status",String.class)
|
Pattern ok_status = op.getOptionalStaticValue("ok-status", String.class)
|
||||||
.map(Pattern::compile)
|
.map(Pattern::compile)
|
||||||
.orElse(Pattern.compile(DEFAULT_OK_STATUS));
|
.orElse(Pattern.compile(DEFAULT_OK_STATUS));
|
||||||
|
|
||||||
@@ -99,7 +117,7 @@ public class HttpOpDispenser extends BaseOpDispenser<HttpOp,HttpSpace> {
|
|||||||
reqF.apply(cycle),
|
reqF.apply(cycle),
|
||||||
ok_status,
|
ok_status,
|
||||||
ok_body,
|
ok_body,
|
||||||
ctxF.apply(cycle),cycle
|
ctxF.apply(cycle), cycle
|
||||||
);
|
);
|
||||||
return opFunc;
|
return opFunc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,6 +141,9 @@ defaults:
|
|||||||
ensure that the values that are inserted at binding points are produced
|
ensure that the values that are inserted at binding points are produced
|
||||||
in a valid form for a URI. You can use the `URLEncode()`
|
in a valid form for a URI. You can use the `URLEncode()`
|
||||||
binding function where needed to achieve this.
|
binding function where needed to achieve this.
|
||||||
|
*NOTE*, If you are using dynamic values for the uri field, and
|
||||||
|
a test value for cycle 0 includes neither `URLENCODE[[` nor `E[]`,
|
||||||
|
then it is skipped. You can override this with `enable_urlencode: true`.
|
||||||
- **method** - An optional request method. If not provided, "GET" is
|
- **method** - An optional request method. If not provided, "GET" is
|
||||||
assumed. Any method name will work here, even custom ones that are
|
assumed. Any method name will work here, even custom ones that are
|
||||||
specific to a given target system. No validation is done for standard
|
specific to a given target system. No validation is done for standard
|
||||||
@@ -187,11 +190,22 @@ configuration. If needed, more configurable SSL support will be added.
|
|||||||
|
|
||||||
## Client Behavior
|
## Client Behavior
|
||||||
|
|
||||||
### TCP Sessions
|
### TCP Sessions & Clients
|
||||||
|
|
||||||
The HTTP clients are allocated one to each thread. The TCP connection
|
Client instances are created for each unique `space` value. NoSQLBench
|
||||||
caching is entirely left to the defaults for the current HttpClient
|
provides a way for all driver adapters to instance native clients according
|
||||||
library that is bundled within the JVM.
|
to a data from a binding. This is standardized under the op template parameter
|
||||||
|
`space`, which is wired by default to the static value `default`. This means
|
||||||
|
that each activity that uses the http driver shares a client instance across
|
||||||
|
all threads by default. If you want to have a new http client per-thread,
|
||||||
|
simply add a binding for `space: ThreadNumToInteger()` and reference it in
|
||||||
|
an op template like `space: {space}`, OR use an inline op field in your op
|
||||||
|
template like `space: {{ThreadNumToInteger()}}`.
|
||||||
|
|
||||||
|
You can use any binding function you want for the space op field. However,
|
||||||
|
if you were to assign it something like "space: {{Identity()}}" you would
|
||||||
|
not have a good result, as you would be spinning up and caching a new http client
|
||||||
|
instance for every single cycle.
|
||||||
|
|
||||||
### Chunked encoding and web sockets
|
### Chunked encoding and web sockets
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user