📄 httpsamplerbase.java
字号:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jmeter.protocol.http.sampler;
import java.io.ByteArrayOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.jmeter.config.Argument;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.engine.event.LoopIterationEvent;
import org.apache.jmeter.protocol.http.control.AuthManager;
import org.apache.jmeter.protocol.http.control.CookieManager;
import org.apache.jmeter.protocol.http.control.HeaderManager;
import org.apache.jmeter.protocol.http.parser.HTMLParseException;
import org.apache.jmeter.protocol.http.parser.HTMLParser;
import org.apache.jmeter.protocol.http.util.EncoderCache;
import org.apache.jmeter.protocol.http.util.HTTPArgument;
import org.apache.jmeter.protocol.http.util.HTTPConstantsInterface;
import org.apache.jmeter.samplers.AbstractSampler;
import org.apache.jmeter.samplers.Entry;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.TestListener;
import org.apache.jmeter.testelement.ThreadListener;
import org.apache.jmeter.testelement.property.BooleanProperty;
import org.apache.jmeter.testelement.property.IntegerProperty;
import org.apache.jmeter.testelement.property.JMeterProperty;
import org.apache.jmeter.testelement.property.PropertyIterator;
import org.apache.jmeter.testelement.property.StringProperty;
import org.apache.jmeter.testelement.property.TestElementProperty;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.jorphan.util.JOrphanUtils;
import org.apache.log.Logger;
import org.apache.oro.text.MalformedCachePatternException;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.Perl5Matcher;
/**
* Common constants and methods for HTTP samplers
*
*/
public abstract class HTTPSamplerBase extends AbstractSampler
implements TestListener, ThreadListener, HTTPConstantsInterface {
private static final Logger log = LoggingManager.getLoggerForClass();
public final static String ARGUMENTS = "HTTPsampler.Arguments"; // $NON-NLS-1$
public final static String AUTH_MANAGER = "HTTPSampler.auth_manager"; // $NON-NLS-1$
public final static String COOKIE_MANAGER = "HTTPSampler.cookie_manager"; // $NON-NLS-1$
public final static String HEADER_MANAGER = "HTTPSampler.header_manager"; // $NON-NLS-1$
public final static String MIMETYPE = "HTTPSampler.mimetype"; // $NON-NLS-1$
public final static String DOMAIN = "HTTPSampler.domain"; // $NON-NLS-1$
public final static String PORT = "HTTPSampler.port"; // $NON-NLS-1$
public final static String METHOD = "HTTPSampler.method"; // $NON-NLS-1$
public final static String CONTENT_ENCODING = "HTTPSampler.contentEncoding"; // $NON-NLS-1$
public final static String IMPLEMENTATION = "HTTPSampler.implementation"; // $NON-NLS-1$
public final static String PATH = "HTTPSampler.path"; // $NON-NLS-1$
public final static String FOLLOW_REDIRECTS = "HTTPSampler.follow_redirects"; // $NON-NLS-1$
public final static String AUTO_REDIRECTS = "HTTPSampler.auto_redirects"; // $NON-NLS-1$
public final static String PROTOCOL = "HTTPSampler.protocol"; // $NON-NLS-1$
private static final String PROTOCOL_FILE = "file"; // $NON-NLS-1$
private final static String DEFAULT_PROTOCOL = PROTOCOL_HTTP;
public final static String URL = "HTTPSampler.URL"; // $NON-NLS-1$
public static final String CLIENT = "HTTPSampler.client"; // $NON-NLS-1$
public final static String DEFAULT_METHOD = GET; // $NON-NLS-1$
// Supported methods:
private final static String [] METHODS = {
DEFAULT_METHOD, // i.e. GET
POST,
HEAD,
PUT,
OPTIONS,
TRACE,
DELETE,
};
private final static List METHODLIST = Collections.unmodifiableList(Arrays.asList(METHODS));
public final static String USE_KEEPALIVE = "HTTPSampler.use_keepalive"; // $NON-NLS-1$
public final static String FILE_NAME = "HTTPSampler.FILE_NAME"; // $NON-NLS-1$
public final static String DO_MULTIPART_POST = "HTTPSampler.DO_MULTIPART_POST"; // $NON-NLS-1$
/* Shown as Parameter Name on the GUI */
public final static String FILE_FIELD = "HTTPSampler.FILE_FIELD"; // $NON-NLS-1$
// public final static String FILE_DATA = "HTTPSampler.FILE_DATA"; // $NON-NLS-1$
// public final static String FILE_MIMETYPE = "HTTPSampler.FILE_MIMETYPE"; // $NON-NLS-1$
public final static String CONTENT_TYPE = "HTTPSampler.CONTENT_TYPE"; // $NON-NLS-1$
// public final static String NORMAL_FORM = "normal_form"; // $NON-NLS-1$
// public final static String MULTIPART_FORM = "multipart_form"; // $NON-NLS-1$
// public final static String ENCODED_PATH= "HTTPSampler.encoded_path";
// IMAGE_PARSER now really means EMBEDDED_PARSER
public final static String IMAGE_PARSER = "HTTPSampler.image_parser"; // $NON-NLS-1$
// Embedded URLs must match this RE (if provided)
public final static String EMBEDDED_URL_RE = "HTTPSampler.embedded_url_re"; // $NON-NLS-1$
public final static String MONITOR = "HTTPSampler.monitor"; // $NON-NLS-1$
/** A number to indicate that the port has not been set. * */
public static final int UNSPECIFIED_PORT = 0;
public static final String UNSPECIFIED_PORT_AS_STRING = "0"; // $NON-NLS-1$
protected final static String NON_HTTP_RESPONSE_CODE = "Non HTTP response code";
protected final static String NON_HTTP_RESPONSE_MESSAGE = "Non HTTP response message";
private static final String ARG_VAL_SEP = "="; // $NON-NLS-1$
private static final String QRY_SEP = "&"; // $NON-NLS-1$
private static final String QRY_PFX = "?"; // $NON-NLS-1$
protected static final int MAX_REDIRECTS = JMeterUtils.getPropDefault("httpsampler.max_redirects", 5); // $NON-NLS-1$
protected static final int MAX_FRAME_DEPTH = JMeterUtils.getPropDefault("httpsampler.max_frame_depth", 5); // $NON-NLS-1$
// Derive the mapping of content types to parsers
private static Map parsersForType = new HashMap();
// Not synch, but it is not modified after creation
private static final String RESPONSE_PARSERS= // list of parsers
JMeterUtils.getProperty("HTTPResponse.parsers");//$NON-NLS-1$
static{
String []parsers = JOrphanUtils.split(RESPONSE_PARSERS, " " , true);// returns empty array for null
for (int i=0;i<parsers.length;i++){
final String parser = parsers[i];
String classname=JMeterUtils.getProperty(parser+".className");//$NON-NLS-1$
if (classname == null){
log.info("Cannot find .className property for "+parser+", using default");
classname="";
}
String typelist=JMeterUtils.getProperty(parser+".types");//$NON-NLS-1$
if (typelist != null){
String []types=JOrphanUtils.split(typelist, " " , true);
for (int j=0;j<types.length;j++){
final String type = types[j];
log.info("Parser for "+type+" is "+classname);
parsersForType.put(type,classname);
}
} else {
log.warn("Cannot find .types property for "+parser);
}
}
if (parsers.length==0){ // revert to previous behaviour
parsersForType.put("text/html", ""); //$NON-NLS-1$ //$NON-NLS-2$
log.info("No response parsers defined: text/html only will be scanned for embedded resources");
}
}
////////////////////// Variables //////////////////////
private boolean dynamicPath = false;// Set false if spaces are already encoded
////////////////////// Code ///////////////////////////
public HTTPSamplerBase() {
setArguments(new Arguments());
}
/**
* The name parameter to be applied to the file
*/
public void setFileField(String value) {
setProperty(FILE_FIELD, value);
}
/**
* The name parameter to be applied to the file
*/
public String getFileField() {
return getPropertyAsString(FILE_FIELD);
}
/**
* The actual name of the file to POST
*/
public void setFilename(String value) {
setProperty(FILE_NAME, value);
}
/**
* The actual name of the file to POST
*/
public String getFilename() {
return getPropertyAsString(FILE_NAME);
}
/**
* Determine if the file should be sent as the entire Post body,
* i.e. without any additional wrapping
*
* @return true if specified file is to be sent as the body,
* i.e. FileField is blank
*/
public boolean getSendFileAsPostBody() {
// If no file field is specified, the file is sent as post body
return getFileField().length()== 0 && getFilename().length() > 0;
}
/**
* Determine if none of the parameters have a name, and if that
* is the case, it means that the parameter values should be sent
* as the post body
*
* @return true if none of the parameters have a name specified
*/
public boolean getSendParameterValuesAsPostBody() {
boolean noArgumentsHasName = true;
PropertyIterator args = getArguments().iterator();
while (args.hasNext()) {
HTTPArgument arg = (HTTPArgument) args.next().getObjectValue();
if(arg.getName() != null && arg.getName().length() > 0) {
noArgumentsHasName = false;
break;
}
}
return noArgumentsHasName;
}
/**
* Determine if we should use multipart/form-data or
* application/x-www-form-urlencoded for the post
*
* @return true if multipart/form-data should be used and method is POST
*/
public boolean getUseMultipartForPost(){
// We use multipart if we have been told so, or files are present
// and the files should not be send as the post body
if(POST.equals(getMethod()) && (getDoMultipartPost() || (hasUploadableFiles() && !getSendFileAsPostBody()))) {
return true;
}
else {
return false;
}
}
public void setProtocol(String value) {
setProperty(PROTOCOL, value.toLowerCase());
}
public String getProtocol() {
String protocol = getPropertyAsString(PROTOCOL);
if (protocol == null || protocol.length() == 0 ) {
return DEFAULT_PROTOCOL;
}
return protocol;
}
public String getClient() {// TODO should it have a default?
return getPropertyAsString(CLIENT);
}
public void setClient(String client){
setProperty(CLIENT,client);
}
/**
* Sets the Path attribute of the UrlConfig object Also calls parseArguments
* to extract and store any query arguments
*
* @param path
* The new Path value
*/
public void setPath(String path) {
// We know that URL arguments should always be encoded in UTF-8 according to spec
setPath(path, EncoderCache.URL_ARGUMENT_ENCODING);
}
/**
* Sets the Path attribute of the UrlConfig object Also calls parseArguments
* to extract and store any query arguments
*
* @param path
* The new Path value
* @param contentEncoding
* The encoding used for the querystring parameter values
*/
public void setPath(String path, String contentEncoding) {
if (GET.equals(getMethod()) || DELETE.equals(getMethod())) {
int index = path.indexOf(QRY_PFX);
if (index > -1) {
setProperty(PATH, path.substring(0, index));
// Parse the arguments in querystring, assuming specified encoding for values
parseArguments(path.substring(index + 1), contentEncoding);
} else {
setProperty(PATH, path);
}
} else {
setProperty(PATH, path);
}
}
public String getPath() {
String p = getPropertyAsString(PATH);
if (dynamicPath) {
return encodeSpaces(p);
}
return p;
}
public void setFollowRedirects(boolean value) {
setProperty(new BooleanProperty(FOLLOW_REDIRECTS, value));
}
public boolean getFollowRedirects() {
return getPropertyAsBoolean(FOLLOW_REDIRECTS);
}
public void setAutoRedirects(boolean value) {
setProperty(new BooleanProperty(AUTO_REDIRECTS, value));
}
public boolean getAutoRedirects() {
return getPropertyAsBoolean(AUTO_REDIRECTS);
}
public void setMethod(String value) {
setProperty(METHOD, value);
}
public String getMethod() {
return getPropertyAsString(METHOD);
}
public void setContentEncoding(String value) {
setProperty(CONTENT_ENCODING, value);
}
public String getContentEncoding() {
return getPropertyAsString(CONTENT_ENCODING);
}
public void setUseKeepAlive(boolean value) {
setProperty(new BooleanProperty(USE_KEEPALIVE, value));
}
public boolean getUseKeepAlive() {
return getPropertyAsBoolean(USE_KEEPALIVE);
}
public void setDoMultipartPost(boolean value) {
setProperty(new BooleanProperty(DO_MULTIPART_POST, value));
}
public boolean getDoMultipartPost() {
return getPropertyAsBoolean(DO_MULTIPART_POST, false);
}
public void setMonitor(String value) {
this.setProperty(MONITOR, value);
}
public void setMonitor(boolean truth) {
this.setProperty(MONITOR, truth);
}
public String getMonitor() {
return this.getPropertyAsString(MONITOR);
}
public boolean isMonitor() {
return this.getPropertyAsBoolean(MONITOR);
}
public void setImplementation(String value) {
this.setProperty(IMPLEMENTATION, value);
}
public String getImplementation() {
return this.getPropertyAsString(IMPLEMENTATION);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -