Skip to content
Permalink
Browse files
Add a switch to decide which regex engine should be used
  • Loading branch information
FSchumacher committed Mar 5, 2022
1 parent 4e21125 commit d61b9d3550dcf8757d9bdfe70fb64e20f63f9211
Showing 1 changed file with 121 additions and 75 deletions.
@@ -18,6 +18,8 @@
package org.apache.jmeter.protocol.http.modifier;

import java.io.Serializable;
import java.util.function.Function;
import java.util.regex.Matcher;

import org.apache.jmeter.processor.PreProcessor;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase;
@@ -41,15 +43,11 @@ public class URLRewritingModifier extends AbstractTestElement implements Seriali

private static final String SEMI_COLON = ";"; // $NON-NLS-1$

private transient Pattern pathExtensionEqualsQuestionmarkRegexp;

private transient Pattern pathExtensionEqualsNoQuestionmarkRegexp;

private transient Pattern parameterRegexp;

private transient Pattern pathExtensionNoEqualsQuestionmarkRegexp;

private transient Pattern pathExtensionNoEqualsNoQuestionmarkRegexp;
private transient Function<String, String> pathExtensionEqualsQuestionmarkExtractor;
private transient Function<String, String> pathExtensionEqualsNoQuestionmarkExtractor;
private transient Function<String, String> pathExtensionNoEqualsQuestionmarkExtractor;
private transient Function<String, String> pathExtensionNoEqualsNoQuestionmarkExtractor;
private transient Function<String, String> parameterExtractor;

private static final String ARGUMENT_NAME = "argument_name"; // $NON-NLS-1$

@@ -63,6 +61,8 @@ public class URLRewritingModifier extends AbstractTestElement implements Seriali

private static final String ENCODE = "encode"; // $NON-NLS-1$

private boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false);

// PreProcessors are cloned per-thread, so this will be saved per-thread
private transient String savedValue = ""; // $NON-NLS-1$

@@ -79,46 +79,21 @@ public void process() {
}
initRegex(getArgumentName());
String text = responseText.getResponseDataAsString();
Perl5Matcher matcher = JMeterUtils.getMatcher();
String value = "";
String value;
if (isPathExtension() && isPathExtensionNoEquals() && isPathExtensionNoQuestionmark()) {
if (matcher.contains(text, pathExtensionNoEqualsNoQuestionmarkRegexp)) {
MatchResult result = matcher.getMatch();
value = result.group(1);
}
} else if (isPathExtension() && isPathExtensionNoEquals()) // && !isPathExtensionNoQuestionmark()
{
if (matcher.contains(text, pathExtensionNoEqualsQuestionmarkRegexp)) {
MatchResult result = matcher.getMatch();
value = result.group(1);
}
} else if (isPathExtension() && isPathExtensionNoQuestionmark()) // && !isPathExtensionNoEquals()
{
if (matcher.contains(text, pathExtensionEqualsNoQuestionmarkRegexp)) {
MatchResult result = matcher.getMatch();
value = result.group(1);
}
} else if (isPathExtension()) // && !isPathExtensionNoEquals() && !isPathExtensionNoQuestionmark()
{
if (matcher.contains(text, pathExtensionEqualsQuestionmarkRegexp)) {
MatchResult result = matcher.getMatch();
value = result.group(1);
}
} else // if ! isPathExtension()
{
if (matcher.contains(text, parameterRegexp)) {
MatchResult result = matcher.getMatch();
for (int i = 1; i < result.groups(); i++) {
value = result.group(i);
if (value != null) {
break;
}
}
}
value = pathExtensionEqualsQuestionmarkExtractor.apply(text);
} else if (isPathExtension() && isPathExtensionNoEquals()) { // && !isPathExtensionNoQuestionmark()
value = pathExtensionEqualsNoQuestionmarkExtractor.apply(text);
} else if (isPathExtension() && isPathExtensionNoQuestionmark()) { // && !isPathExtensionNoEquals()
value = pathExtensionNoEqualsQuestionmarkExtractor.apply(text);
} else if (isPathExtension()) { // && !isPathExtensionNoEquals() && !isPathExtensionNoQuestionmark()
value = pathExtensionNoEqualsNoQuestionmarkExtractor.apply(text);
} else { // if ! isPathExtension()
value = parameterExtractor.apply(text);
}

// Bug 15025 - save session value across samplers
if (shouldCache()){
if (shouldCache()) {
if (value == null || value.isEmpty()) {
value = savedValue;
} else {
@@ -158,42 +133,113 @@ public void setArgumentName(String argName) {

private void initRegex(String argName) {
String quotedArg = Perl5Compiler.quotemeta(argName);// Don't get tripped up by RE chars in the arg name
pathExtensionEqualsQuestionmarkRegexp = JMeterUtils.getPatternCache().getPattern(
SEMI_COLON + quotedArg + "=([^\"'<>&\\s;]*)", // $NON-NLS-1$
Perl5Compiler.MULTILINE_MASK | Perl5Compiler.READ_ONLY_MASK);
pathExtensionEqualsQuestionmarkExtractor = generateExtractor(
SEMI_COLON + quotedArg + "=([^\"'<>&\\s;]*)" // $NON-NLS-1$
);
pathExtensionEqualsNoQuestionmarkExtractor = generateExtractor(
SEMI_COLON + quotedArg + "=([^\"'<>&\\s;?]*)" // $NON-NLS-1$
);
pathExtensionNoEqualsQuestionmarkExtractor = generateExtractor(
SEMI_COLON + quotedArg + "([^\"'<>&\\s;]*)"// $NON-NLS-1$
);
pathExtensionNoEqualsNoQuestionmarkExtractor = generateExtractor(
SEMI_COLON + quotedArg + "([^\"'<>&\\s;?]*)" // $NON-NLS-1$
);

parameterExtractor = generateFirstMatchExtractor(
// ;sessionid=value
"[;\\?&]" + quotedArg + "=([^\"'<>&\\s;\\\\]*)" // $NON-NLS-1$

// name="sessionid" value="value"
+ "|\\s[Nn][Aa][Mm][Ee]\\s*=\\s*[\"']" + quotedArg
+ "[\"']" + "[^>]*" // $NON-NLS-1$
+ "\\s[vV][Aa][Ll][Uu][Ee]\\s*=\\s*[\"']" // $NON-NLS-1$
+ "([^\"']*)" + "[\"']" // $NON-NLS-1$

// value="value" name="sessionid"
+ "|\\s[vV][Aa][Ll][Uu][Ee]\\s*=\\s*[\"']" // $NON-NLS-1$
+ "([^\"']*)" + "[\"']" + "[^>]*" // $NON-NLS-1$ // $NON-NLS-2$ // $NON-NLS-3$
+ "\\s[Nn][Aa][Mm][Ee]\\s*=\\s*[\"']" // $NON-NLS-1$
+ quotedArg + "[\"']" // $NON-NLS-1$
);
// NOTE: the handling of simple- vs. double-quotes could be formally
// more accurate, but I can't imagine a session id containing
// either, so we should be OK. The whole set of expressions is a
// quick hack anyway, so who cares.
}

pathExtensionEqualsNoQuestionmarkRegexp = JMeterUtils.getPatternCache().getPattern(
SEMI_COLON + quotedArg + "=([^\"'<>&\\s;?]*)", // $NON-NLS-1$
Perl5Compiler.MULTILINE_MASK | Perl5Compiler.READ_ONLY_MASK);
private Function<String, String> generateExtractor(String regex) {
if (useJavaRegex) {
return generateExtractorWithJavaRegex(regex);
}
return generateExtractorWithOroRegex(regex);
}

pathExtensionNoEqualsQuestionmarkRegexp = JMeterUtils.getPatternCache().getPattern(
SEMI_COLON + quotedArg + "([^\"'<>&\\s;]*)", // $NON-NLS-1$
Perl5Compiler.MULTILINE_MASK | Perl5Compiler.READ_ONLY_MASK);
private Function<String, String> generateExtractorWithJavaRegex(String regex) {
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(
regex,
java.util.regex.Pattern.MULTILINE);
return text -> {
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
return matcher.group(1);
}
return "";
};
}

pathExtensionNoEqualsNoQuestionmarkRegexp = JMeterUtils.getPatternCache().getPattern(
SEMI_COLON + quotedArg + "([^\"'<>&\\s;?]*)", // $NON-NLS-1$
private Function<String, String> generateExtractorWithOroRegex(String regex) {
Pattern pattern = JMeterUtils.getPatternCache().getPattern(
regex,
Perl5Compiler.MULTILINE_MASK | Perl5Compiler.READ_ONLY_MASK);
Perl5Matcher matcher = JMeterUtils.getMatcher();
return text -> {
if (matcher.contains(text, pattern)) {
MatchResult result = matcher.getMatch();
return result.group(1);
}
return "";
};
}

parameterRegexp = JMeterUtils.getPatternCache().getPattern(
// ;sessionid=value
"[;\\?&]" + quotedArg + "=([^\"'<>&\\s;\\\\]*)" + // $NON-NLS-1$

// name="sessionid" value="value"
"|\\s[Nn][Aa][Mm][Ee]\\s*=\\s*[\"']" + quotedArg
+ "[\"']" + "[^>]*" // $NON-NLS-1$
+ "\\s[vV][Aa][Ll][Uu][Ee]\\s*=\\s*[\"']" // $NON-NLS-1$
+ "([^\"']*)" + "[\"']" // $NON-NLS-1$

// value="value" name="sessionid"
+ "|\\s[vV][Aa][Ll][Uu][Ee]\\s*=\\s*[\"']" // $NON-NLS-1$
+ "([^\"']*)" + "[\"']" + "[^>]*" // $NON-NLS-1$ // $NON-NLS-2$ // $NON-NLS-3$
+ "\\s[Nn][Aa][Mm][Ee]\\s*=\\s*[\"']" // $NON-NLS-1$
+ quotedArg + "[\"']", // $NON-NLS-1$
private Function<String, String> generateFirstMatchExtractor(String regex) {
if (useJavaRegex) {
return generateFirstMatchExtractorWithJavaRegex(regex);
}
return generateFirstMatchExtractorWithOroRegex(regex);
}

private Function<String, String> generateFirstMatchExtractorWithJavaRegex(String regex) {
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(
regex,
java.util.regex.Pattern.MULTILINE);
return text -> {
Matcher matcher = pattern.matcher(text);
for (int i = 1; i < matcher.groupCount(); i++) {
String value = matcher.group(i);
if (value != null) {
return value;
}
}
return "";
};
}

private Function<String, String> generateFirstMatchExtractorWithOroRegex(String regex) {
Pattern pattern = JMeterUtils.getPatternCache().getPattern(
regex,
Perl5Compiler.MULTILINE_MASK | Perl5Compiler.READ_ONLY_MASK);
// NOTE: the handling of simple- vs. double-quotes could be formally
// more accurate, but I can't imagine a session id containing
// either, so we should be OK. The whole set of expressions is a
// quick hack anyway, so who cares.
Perl5Matcher matcher = JMeterUtils.getMatcher();
return text -> {
MatchResult result = matcher.getMatch();
for (int i = 1; i < result.groups(); i++) {
String value = result.group(i);
if (value != null) {
return value;
}
}
return "";
};
}

public String getArgumentName() {

0 comments on commit d61b9d3

Please sign in to comment.