You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jmeter-dev@jakarta.apache.org by se...@apache.org on 2007/07/03 21:39:52 UTC
svn commit: r552959 - in /jakarta/jmeter/branches/rel-2-2:
src/protocol/http/org/apache/jmeter/protocol/http/proxy/
src/protocol/http/org/apache/jmeter/protocol/http/sampler/
src/protocol/http/org/apache/jmeter/protocol/http/util/
test/src/org/apache/j...
Author: sebb
Date: Tue Jul 3 12:39:51 2007
New Revision: 552959
URL: http://svn.apache.org/viewvc?view=rev&rev=552959
Log:
Bug 42173 - Let HTTP Proxy handle encoding of request, and undecode parameter values
Modified:
jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/proxy/Daemon.java
jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/proxy/HttpRequestHdr.java
jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/proxy/Proxy.java
jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/util/HTTPArgument.java
jakarta/jmeter/branches/rel-2-2/test/src/org/apache/jmeter/protocol/http/proxy/TestHttpRequestHdr.java
jakarta/jmeter/branches/rel-2-2/xdocs/changes.xml
Modified: jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/proxy/Daemon.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/proxy/Daemon.java?view=diff&rev=552959&r1=552958&r2=552959
==============================================================================
--- jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/proxy/Daemon.java (original)
+++ jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/proxy/Daemon.java Tue Jul 3 12:39:51 2007
@@ -22,6 +22,9 @@
import java.io.InterruptedIOException;
import java.net.ServerSocket;
import java.net.Socket;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
@@ -67,6 +70,11 @@
*/
private Class proxyClass = Proxy.class;
+ /** A Map of url string to page character encoding of that page */
+ private Map pageEncodings;
+ /** A Map of url string to character encoding for the form */
+ private Map formEncodings;
+
/**
* Default constructor.
*/
@@ -161,6 +169,10 @@
running = true;
ServerSocket mainSocket = null;
+ // Maps to contain page and form encodings
+ pageEncodings = Collections.synchronizedMap(new HashMap());
+ formEncodings = Collections.synchronizedMap(new HashMap());
+
try {
log.info("Creating Daemon Socket... on port " + daemonPort);
mainSocket = new ServerSocket(daemonPort);
@@ -174,7 +186,7 @@
if (running) {
// Pass request to new proxy thread
Proxy thd = (Proxy) proxyClass.newInstance();
- thd.configure(clientSocket, target);
+ thd.configure(clientSocket, target, pageEncodings, formEncodings);
thd.start();
} else {
// The socket was accepted after we were told to stop.
@@ -199,6 +211,10 @@
} catch (Exception exc) {
}
}
+
+ // Clear maps
+ pageEncodings = null;
+ formEncodings = null;
}
/**
Modified: jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/proxy/HttpRequestHdr.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/proxy/HttpRequestHdr.java?view=diff&rev=552959&r1=552958&r2=552959
==============================================================================
--- jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/proxy/HttpRequestHdr.java (original)
+++ jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/proxy/HttpRequestHdr.java Tue Jul 3 12:39:51 2007
@@ -21,6 +21,10 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.ProtocolException;
+import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -38,6 +42,7 @@
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.logging.LoggingManager;
+import org.apache.jorphan.util.JOrphanUtils;
import org.apache.log.Logger;
//For unit tests, @see TestHttpRequestHdr
@@ -71,7 +76,7 @@
*/
private String version = ""; // NOTREAD // $NON-NLS-1$
- private String postData = ""; // $NON-NLS-1$
+ private byte[] rawPostData;
private Map headers = new HashMap();
@@ -134,9 +139,11 @@
readLength++;
}
}
- postData = line.toString();
+ // Keep the raw post data
+ rawPostData = line.toByteArray();
+
if (log.isDebugEnabled()){
- log.debug("postData: " + postData);
+ log.debug("rawPostData in default JRE encoding: " + new String(rawPostData));
log.debug("Request: " + clientRequest.toString());
}
return clientRequest.toByteArray();
@@ -198,7 +205,8 @@
return headerManager;
}
- public HTTPSamplerBase getSampler() {
+ public HTTPSamplerBase getSampler(Map pageEncodings, Map formEncodings)
+ throws MalformedURLException, IOException, ProtocolException {
// Damn! A whole new GUI just to instantiate a test element?
// Isn't there a beter way?
HttpTestSampleGui tempGui = null;
@@ -210,7 +218,9 @@
tempGui = new HttpTestSampleGui();
}
sampler.setProperty(TestElement.GUI_CLASS, tempGui.getClass().getName());
- populateSampler();
+
+ // Populate the sampler
+ populateSampler(pageEncodings, formEncodings);
tempGui.configure(sampler);
tempGui.modifyTestElement(sampler);
@@ -222,6 +232,19 @@
log.debug("getSampler: sampler path = " + sampler.getPath());
return sampler;
}
+
+ /**
+ *
+ * @return
+ * @throws MalformedURLException
+ * @throws IOException
+ * @throws ProtocolException
+ * @deprecated use the getSampler(HashMap pageEncodings, HashMap formEncodings) instead, since
+ * that properly handles the encodings of the page
+ */
+ public HTTPSamplerBase getSampler() throws MalformedURLException, IOException, ProtocolException {
+ return getSampler(null, null);
+ }
private String getContentType() {
Header contentTypeHeader = (Header) headers.get(CONTENT_TYPE);
@@ -231,6 +254,24 @@
return null;
}
+ private String getContentEncoding() {
+ String contentType = getContentType();
+ if(contentType != null) {
+ int charSetStartPos = contentType.toLowerCase().indexOf("charset=");
+ if(charSetStartPos >= 0) {
+ String charSet = contentType.substring(charSetStartPos + "charset=".length());
+ if(charSet != null && charSet.length() > 0) {
+ // Remove quotes if present
+ charSet = JOrphanUtils.replaceAllChars(charSet, '"', "");
+ if(charSet.length() > 0) {
+ return charSet;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
private boolean isMultipart(String contentType) {
if (contentType != null && contentType.startsWith(HTTPSamplerBase.MULTIPART_FORM_DATA)) {
return true;
@@ -250,22 +291,13 @@
}
}
- private void populateSampler() {
- sampler.setDomain(serverName());
+ private void populateSampler(Map pageEncodings, Map formEncodings)
+ throws MalformedURLException, UnsupportedEncodingException {
+ sampler.setDomain(serverName());
if (log.isDebugEnabled())
log.debug("Proxy: setting server: " + sampler.getDomain());
sampler.setMethod(method);
log.debug("Proxy: method server: " + sampler.getMethod());
- sampler.setPath(serverUrl());
- if (log.isDebugEnabled())
- log.debug("Proxy: setting path: " + sampler.getPath());
- if (numberRequests) {
- requestNumber++;
- sampler.setName(requestNumber + " " + sampler.getPath());
- } else {
- sampler.setName(sampler.getPath());
- }
- sampler.setPort(serverPort());
if (log.isDebugEnabled())
log.debug("Proxy: setting port: " + sampler.getPort());
if (url.indexOf("//") > -1) {
@@ -273,7 +305,7 @@
if (log.isDebugEnabled())
log.debug("Proxy: setting protocol to : " + protocol);
sampler.setProtocol(protocol);
- } else if (sampler.getPort() == 443) {
+ } else if (sampler.getPort() == HTTPSamplerBase.DEFAULT_HTTPS_PORT) {
sampler.setProtocol(HTTPS);
if (log.isDebugEnabled())
log.debug("Proxy: setting protocol to https");
@@ -283,6 +315,82 @@
sampler.setProtocol(HTTP);
}
+ URL pageUrl = null;
+ if(sampler.isProtocolDefaultPort()) {
+ pageUrl = new URL(sampler.getProtocol(), sampler.getDomain(), serverUrl());
+ }
+ else {
+ pageUrl = new URL(sampler.getProtocol(), sampler.getDomain(), sampler.getPort(), serverUrl());
+ }
+ String urlWithoutQuery = getUrlWithoutQuery(pageUrl);
+
+
+ // Check if the request itself tells us what the encoding is
+ String contentEncoding = null;
+ String requestContentEncoding = getContentEncoding();
+ if(requestContentEncoding != null) {
+ contentEncoding = requestContentEncoding;
+ }
+ else {
+ // Check if we know the encoding of the page
+ if (pageEncodings != null) {
+ synchronized (pageEncodings) {
+ contentEncoding = (String) pageEncodings.get(urlWithoutQuery);
+ }
+ }
+ // Check if we know the encoding of the form
+ if (formEncodings != null) {
+ synchronized (formEncodings) {
+ String formEncoding = (String) formEncodings.get(urlWithoutQuery);
+ // Form encoding has priority over page encoding
+ if (formEncoding != null) {
+ contentEncoding = formEncoding;
+ }
+ }
+ }
+ }
+
+ // Get the post data using the content encoding of the request
+ String postData = null;
+ if (log.isDebugEnabled()) {
+ if(contentEncoding != null) {
+ log.debug("Using encoding " + contentEncoding + " for request body");
+ }
+ else {
+ log.debug("No encoding found, using JRE default encoding for request body");
+ }
+ }
+ if (contentEncoding != null) {
+ postData = new String(rawPostData, contentEncoding);
+ } else {
+ // Use default encoding
+ postData = new String(rawPostData);
+ }
+
+ if(contentEncoding != null) {
+ sampler.setPath(serverUrl(), contentEncoding);
+ }
+ else {
+ // Although the spec says UTF-8 should be used for encoding URL parameters,
+ // most browser use ISO-8859-1 for default if encoding is not known.
+ // We use null for contentEncoding, then the url parameters will be added
+ // with the value in the URL, and the "encode?" flag set to false
+ sampler.setPath(serverUrl(), null);
+ }
+ if (log.isDebugEnabled())
+ log.debug("Proxy: setting path: " + sampler.getPath());
+ if (numberRequests) {
+ requestNumber++;
+ sampler.setName(requestNumber + " " + sampler.getPath());
+ } else {
+ sampler.setName(sampler.getPath());
+ }
+
+ // Set the content encoding
+ if(contentEncoding != null) {
+ sampler.setContentEncoding(contentEncoding);
+ }
+
// If it was a HTTP GET request, then all parameters in the URL
// has been handled by the sampler.setPath above, so we just need
// to do parse the rest of the request if it is not a GET request
@@ -316,7 +424,7 @@
// It is the most common post request, with parameter name and values
// We also assume this if no content type is present, to be most backwards compatible,
// but maybe we should only parse arguments if the content type is as expected
- sampler.parseArguments(postData); //standard name=value postData
+ sampler.parseArguments(postData.trim(), contentEncoding); //standard name=value postData
} else if (postData != null && postData.length() > 0) {
// Just put the whole postbody as the value of a parameter
sampler.addNonEncodedArgument("", postData, ""); //used when postData is pure xml (ex. an xml-rpc call)
@@ -431,4 +539,14 @@
return strBuff.toString();
}
+ private String getUrlWithoutQuery(URL url) {
+ String fullUrl = url.toString();
+ String urlWithoutQuery = fullUrl;
+ String query = url.getQuery();
+ if(query != null) {
+ // Get rid of the query and the ?
+ urlWithoutQuery = urlWithoutQuery.substring(0, urlWithoutQuery.length() - query.length() - 1);
+ }
+ return urlWithoutQuery;
+ }
}
Modified: jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/proxy/Proxy.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/proxy/Proxy.java?view=diff&rev=552959&r1=552958&r2=552959
==============================================================================
--- jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/proxy/Proxy.java (original)
+++ jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/proxy/Proxy.java Tue Jul 3 12:39:51 2007
@@ -25,8 +25,11 @@
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
+import java.net.URL;
+import java.util.Map;
import org.apache.jmeter.protocol.http.control.HeaderManager;
+import org.apache.jmeter.protocol.http.parser.HTMLParseException;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerFactory;
import org.apache.jmeter.samplers.SampleResult;
@@ -61,6 +64,11 @@
/** Whether to try to spoof as https **/
private boolean httpsSpoof;
+ /** Reference to Deamon's Map of url string to page character encoding of that page */
+ private Map pageEncodings;
+ /** Reference to Deamon's Map of url string to character encoding for the form */
+ private Map formEncodings;
+
/**
* Default constructor - used by newInstance call in Daemon
*/
@@ -88,11 +96,29 @@
* the ProxyControl which will receive the generated sampler
*/
void configure(Socket _clientSocket, ProxyControl _target) {
- this.target = _target;
- this.clientSocket = _clientSocket;
- this.captureHttpHeaders = _target.getCaptureHttpHeaders();
- this.httpsSpoof = target.getHttpsSpoof();
- }
+ configure(_clientSocket, _target, null, null);
+ }
+
+ /**
+ * Configure the Proxy.
+ *
+ * @param clientSocket
+ * the socket connection to the client
+ * @param target
+ * the ProxyControl which will receive the generated sampler
+ * @param pageEncodings
+ * reference to the Map of Deamon, with mappings from page urls to encoding used
+ * @param formEncodingsEncodings
+ * reference to the Map of Deamon, with mappings from form action urls to encoding used
+ */
+ void configure(Socket clientSocket, ProxyControl target, Map pageEncodings, Map formEncodings) {
+ this.target = target;
+ this.clientSocket = clientSocket;
+ this.captureHttpHeaders = target.getCaptureHttpHeaders();
+ this.httpsSpoof = target.getHttpsSpoof();
+ this.pageEncodings = pageEncodings;
+ this.formEncodings = formEncodings;
+ }
/**
* Main processing method for the Proxy object
@@ -118,7 +144,7 @@
// Populate the sampler. It is the same sampler as we sent into
// the constructor of the HttpRequestHdr instance above
- request.getSampler();
+ request.getSampler(pageEncodings, formEncodings);
/*
* Create a Header Manager to ensure that the browsers headers are
@@ -145,7 +171,12 @@
String noHttpsResult = new String(result.getResponseData());
result.setResponseData(noHttpsResult.replaceAll("https", "http").getBytes());
}
-
+
+ // Find the page encoding and possibly encodings for forms in the page
+ // in the response from the web server
+ String pageEncoding = addPageEncoding(result);
+ addFormEncodings(result, pageEncoding);
+
writeToClient(result, new BufferedOutputStream(clientSocket.getOutputStream()));
/*
* We don't want to store any cookies in the generated test plan
@@ -241,4 +272,73 @@
log.warn("Exception while writing error", e);
}
}
-}
\ No newline at end of file
+
+ /**
+ * Add the page encoding of the sample result to the Map with page encodings
+ *
+ * @param result the sample result to check
+ * @return the page encoding found for the sample result, or null
+ */
+ private String addPageEncoding(SampleResult result) {
+ String pageEncoding = getContentEncoding(result);
+ if(pageEncoding != null) {
+ String urlWithoutQuery = getUrlWithoutQuery(result.getURL());
+ synchronized(pageEncodings) {
+ pageEncodings.put(urlWithoutQuery, pageEncoding);
+ }
+ }
+ return pageEncoding;
+ }
+
+ /**
+ * Add the form encodings for all forms in the sample result
+ *
+ * @param result the sample result to check
+ * @param pageEncoding the encoding used for the sample result page
+ */
+ private void addFormEncodings(SampleResult result, String pageEncoding) {
+ FormCharSetFinder finder = new FormCharSetFinder();
+ try {
+ finder.addFormActionsAndCharSet(result.getResponseDataAsString(), formEncodings, pageEncoding);
+ }
+ catch (HTMLParseException parseException) {
+ log.debug("Unable to parse response, could not find any form character set encodings");
+ }
+ }
+
+ /**
+ * Get the value of the charset of the content-type header of the sample result
+ *
+ * @param res the sample result to find the charset for
+ * @return the charset found, or null
+ */
+ private String getContentEncoding(SampleResult res) {
+ String contentTypeHeader = res.getContentType();
+ String charSet = null;
+ if (contentTypeHeader != null) {
+ int charSetStartPos = contentTypeHeader.toLowerCase().indexOf("charset=");
+ if (charSetStartPos > 0) {
+ charSet = contentTypeHeader.substring(charSetStartPos + "charset=".length());
+ if (charSet != null) {
+ if (charSet.trim().length() > 0) {
+ charSet = charSet.trim();
+ } else {
+ charSet = null;
+ }
+ }
+ }
+ }
+ return charSet;
+ }
+
+ private String getUrlWithoutQuery(URL url) {
+ String fullUrl = url.toString();
+ String urlWithoutQuery = fullUrl;
+ String query = url.getQuery();
+ if(query != null) {
+ // Get rid of the query and the ?
+ urlWithoutQuery = urlWithoutQuery.substring(0, urlWithoutQuery.length() - query.length() - 1);
+ }
+ return urlWithoutQuery;
+ }
+}
Modified: jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java?view=diff&rev=552959&r1=552958&r2=552959
==============================================================================
--- jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java (original)
+++ jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java Tue Jul 3 12:39:51 2007
@@ -361,18 +361,33 @@
* The new Path value
*/
public void setPath(String path) {
- if (GET.equals(getMethod())) {
- int index = path.indexOf(QRY_PFX);
- if (index > -1) {
- setProperty(PATH, path.substring(0, index));
- parseArguments(path.substring(index + 1));
- } else {
- setProperty(PATH, path);
- }
- } else {
- setProperty(PATH, 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())) {
+ 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);
@@ -463,20 +478,44 @@
this.addEncodedArgument(name, value, ARG_VAL_SEP);
}
- public void addEncodedArgument(String name, String value, String metaData) {
+ public void addEncodedArgument(String name, String value, String metaData, String contentEncoding) {
if (log.isDebugEnabled()){
- log.debug("adding argument: name: " + name + " value: " + value + " metaData: " + metaData);
+ log.debug("adding argument: name: " + name + " value: " + value + " metaData: " + metaData + " contentEncoding: " + contentEncoding);
}
-
- HTTPArgument arg = new HTTPArgument(name, value, metaData, true);
+ HTTPArgument arg = null;
+ if(contentEncoding != null) {
+ arg = new HTTPArgument(name, value, metaData, true, contentEncoding);
+ }
+ else {
+ arg = new HTTPArgument(name, value, metaData, true);
+ }
- if (arg.getName().equals(arg.getEncodedName()) && arg.getValue().equals(arg.getEncodedValue())) {
+ // Check if there are any difference between name and value and their encoded name and value
+ String valueEncoded = null;
+ if(contentEncoding != null) {
+ try {
+ valueEncoded = arg.getEncodedValue(contentEncoding);
+ }
+ catch (UnsupportedEncodingException e) {
+ log.warn("Unable to get encoded value using encoding " + contentEncoding);
+ valueEncoded = arg.getEncodedValue();
+ }
+ }
+ else {
+ valueEncoded = arg.getEncodedValue();
+ }
+ // If there is no difference, we mark it as not needing encoding
+ if (arg.getName().equals(arg.getEncodedName()) && arg.getValue().equals(valueEncoded)) {
arg.setAlwaysEncoded(false);
}
this.getArguments().addArgument(arg);
}
-
+
+ public void addEncodedArgument(String name, String value, String metaData) {
+ this.addEncodedArgument(name, value, metaData, null);
+ }
+
public void addNonEncodedArgument(String name, String value, String metadata) {
HTTPArgument arg = new HTTPArgument(name, value, metadata, false);
arg.setAlwaysEncoded(false);
@@ -758,22 +797,24 @@
return buf.toString();
}
- // Mark Walsh 2002-08-03, modified to also parse a parameter name value
- // string, where string contains only the parameter name and no equal sign.
- /**
- * This method allows a proxy server to send over the raw text from a
- * browser's output stream to be parsed and stored correctly into the
- * UrlConfig object.
- *
- * For each name found, addArgument() is called
- *
- * @param queryString -
- * the query string
- *
- */
- public void parseArguments(String queryString) {
- String[] args = JOrphanUtils.split(queryString, QRY_SEP);
- for (int i = 0; i < args.length; i++) {
+ // Mark Walsh 2002-08-03, modified to also parse a parameter name value
+ // string, where string contains only the parameter name and no equal sign.
+ /**
+ * This method allows a proxy server to send over the raw text from a
+ * browser's output stream to be parsed and stored correctly into the
+ * UrlConfig object.
+ *
+ * For each name found, addArgument() is called
+ *
+ * @param queryString -
+ * the query string
+ * @param contentEncoding -
+ * the content encoding of the query string. The query string might
+ * actually be the post body of a http post request.
+ */
+ public void parseArguments(String queryString, String contentEncoding) {
+ String[] args = JOrphanUtils.split(queryString, QRY_SEP);
+ for (int i = 0; i < args.length; i++) {
// need to handle four cases:
// - string contains name=value
// - string contains name=
@@ -794,19 +835,26 @@
metaData = "";
name=args[i];
value="";
- }
- if (name.length() > 0) {
- // The browser has already done the encoding, so save the values as is
- HTTPArgument arg = new HTTPArgument(name, value, metaData, false);
- // and make sure they stay that way:
- arg.setAlwaysEncoded(false);
- // Note that URL.encode()/decode() do not follow RFC3986 entirely
- this.getArguments().addArgument(arg);
- // TODO: this leaves the arguments in encoded form, which may be difficult to read
- // if we can find proper coding methods, this could be tidied up
}
- }
- }
+ if (name.length() > 0) {
+ // If we know the encoding, we can decode the argument value,
+ // to make it easier to read for the user
+ if(contentEncoding != null) {
+ addEncodedArgument(name, value, metaData, contentEncoding);
+ }
+ else {
+ // If we do not know the encoding, we just use the encoded value
+ // The browser has already done the encoding, so save the values as is
+ addNonEncodedArgument(name, value, metaData);
+ }
+ }
+ }
+ }
+
+ public void parseArguments(String queryString) {
+ // We do not know the content encoding of the query string
+ parseArguments(queryString, null);
+ }
public String toString() {
try {
@@ -1195,6 +1243,7 @@
res.addSubResult(errorResult(new Exception("Maximum frame/iframe nesting depth exceeded."), res));
} else {
// If we followed redirects, we already have a container:
+ if(!areFollowingRedirect) {
HTTPSampleResult container = (HTTPSampleResult) (areFollowingRedirect ? res.getParent() : res);
// Only download page resources if we were not redirected.
@@ -1203,6 +1252,7 @@
if(!wasRedirected) {
res = downloadPageResources(res, container, frameDepth);
}
+ }
}
}
return res;
Modified: jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/util/HTTPArgument.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/util/HTTPArgument.java?view=diff&rev=552959&r1=552958&r2=552959
==============================================================================
--- jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/util/HTTPArgument.java (original)
+++ jakarta/jmeter/branches/rel-2-2/src/protocol/http/org/apache/jmeter/protocol/http/util/HTTPArgument.java Tue Jul 3 12:39:51 2007
@@ -88,37 +88,65 @@
this(name, value, false);
}
- public HTTPArgument(String name, String value, boolean alreadyEncoded) {
- setAlwaysEncoded(true);
- if (alreadyEncoded) {
- try {
- name = URLDecoder.decode(name, EncoderCache.URL_ARGUMENT_ENCODING);
- value = URLDecoder.decode(value, EncoderCache.URL_ARGUMENT_ENCODING);
- } catch (UnsupportedEncodingException e) {
- // UTF-8 unsupported? You must be joking!
- log.error("UTF-8 encoding not supported!");
- throw new Error(e.toString());
- }
- }
- setName(name);
- setValue(value);
- setMetaData("=");
- }
+ public HTTPArgument(String name, String value, boolean alreadyEncoded) {
+ // We assume the argument value is encoded according to the HTTP spec, i.e. UTF-8
+ this(name, value, alreadyEncoded, EncoderCache.URL_ARGUMENT_ENCODING);
+ }
- public HTTPArgument(String name, String value, String metaData, boolean alreadyEncoded) {
- this(name, value, alreadyEncoded);
- setMetaData(metaData);
- }
+ /**
+ * Construct a new HTTPArgument instance
+ *
+ * @param name the name of the parameter
+ * @param value the value of the parameter
+ * @param alreadyEncoded true if the name and value is already encoded
+ * @param contentEncoding the encoding used for the parameter value
+ */
+ public HTTPArgument(String name, String value, boolean alreadyEncoded, String contentEncoding) {
+ setAlwaysEncoded(true);
+ if (alreadyEncoded) {
+ try {
+ // We assume the name is always encoded according to spec
+ name = URLDecoder.decode(name, EncoderCache.URL_ARGUMENT_ENCODING);
+ // The value is encoded in the specified encoding
+ value = URLDecoder.decode(value, contentEncoding);
+ } catch (UnsupportedEncodingException e) {
+ log.error(contentEncoding + " encoding not supported!");
+ throw new Error(e.toString());
+ }
+ }
+ setName(name);
+ setValue(value);
+ setMetaData("=");
+ }
- public HTTPArgument(Argument arg) {
- this(arg.getName(), arg.getValue(), arg.getMetaData());
- }
+ public HTTPArgument(String name, String value, String metaData, boolean alreadyEncoded) {
+ // We assume the argument value is encoded according to the HTTP spec, i.e. UTF-8
+ this(name, value, metaData, alreadyEncoded, EncoderCache.URL_ARGUMENT_ENCODING);
+ }
- /**
- * Constructor for the Argument object
- */
- public HTTPArgument() {
- }
+ /**
+ * Construct a new HTTPArgument instance
+ *
+ * @param name the name of the parameter
+ * @param value the value of the parameter
+ * @param metaData the separator to use between name and value
+ * @param alreadyEncoded true if the name and value is already encoded
+ * @param contentEncoding the encoding used for the parameter value
+ */
+ public HTTPArgument(String name, String value, String metaData, boolean alreadyEncoded, String contentEncoding) {
+ this(name, value, alreadyEncoded, contentEncoding);
+ setMetaData(metaData);
+ }
+
+ public HTTPArgument(Argument arg) {
+ this(arg.getName(), arg.getValue(), arg.getMetaData());
+ }
+
+ /**
+ * Constructor for the Argument object
+ */
+ public HTTPArgument() {
+ }
/**
* Sets the Name attribute of the Argument object.
Modified: jakarta/jmeter/branches/rel-2-2/test/src/org/apache/jmeter/protocol/http/proxy/TestHttpRequestHdr.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/branches/rel-2-2/test/src/org/apache/jmeter/protocol/http/proxy/TestHttpRequestHdr.java?view=diff&rev=552959&r1=552958&r2=552959
==============================================================================
--- jakarta/jmeter/branches/rel-2-2/test/src/org/apache/jmeter/protocol/http/proxy/TestHttpRequestHdr.java (original)
+++ jakarta/jmeter/branches/rel-2-2/test/src/org/apache/jmeter/protocol/http/proxy/TestHttpRequestHdr.java Tue Jul 3 12:39:51 2007
@@ -20,6 +20,11 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.junit.JMeterTestCase;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase;
@@ -31,115 +36,332 @@
}
public void testRepeatedArguments() throws Exception {
+ String url = "http://localhost/matrix.html";
// A HTTP GET request
- String TEST_GET_REQ =
- "GET http://localhost/matrix.html"
+ String contentEncoding = "UTF-8";
+ String testGetRequest =
+ "GET " + url
+ "?update=yes&d=1&d=2&d=&d=&d=&d=&d=&d=1&d=2&d=1&d=&d= "
- + "HTTP/1.0\n\n";
- HTTPSamplerBase s = getSamplerForRequest(TEST_GET_REQ, "UTF-8");
+ + "HTTP/1.0\r\n\r\n";
+ HTTPSamplerBase s = getSamplerForRequest(url, testGetRequest, contentEncoding);
assertEquals(HTTPSamplerBase.GET, s.getMethod());
-
+ assertEquals(contentEncoding, s.getContentEncoding());
// Check arguments
Arguments arguments = s.getArguments();
assertEquals(13, arguments.getArgumentCount());
- checkArgument((HTTPArgument)arguments.getArgument(0), "update", "yes", "yes", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(1), "d", "1", "1", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(2), "d", "2", "2", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(3), "d", "", "", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(4), "d", "", "", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(5), "d", "", "", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(6), "d", "", "", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(7), "d", "", "", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(8), "d", "1", "1", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(9), "d", "2", "2", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(10), "d", "1", "1", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(11), "d", "", "", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(12), "d", "", "", "UTF-8", false);
+ checkArgument((HTTPArgument)arguments.getArgument(0), "update", "yes", "yes", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(1), "d", "1", "1", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(2), "d", "2", "2", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(3), "d", "", "", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(4), "d", "", "", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(5), "d", "", "", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(6), "d", "", "", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(7), "d", "", "", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(8), "d", "1", "1", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(9), "d", "2", "2", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(10), "d", "1", "1", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(11), "d", "", "", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(12), "d", "", "", contentEncoding, false);
// A HTTP POST request
+ contentEncoding = "UTF-8";
String postBody = "update=yes&d=1&d=2&d=&d=&d=&d=&d=&d=1&d=2&d=1&d=&d=";
- String TEST_POST_REQ = "POST http://localhost/matrix.html HTTP/1.0\n"
+ String testPostRequest = "POST " + url + " HTTP/1.0\n"
+ "Content-type: "
- + HTTPSamplerBase.APPLICATION_X_WWW_FORM_URLENCODED
- + "; charset=UTF-8\r\n"
- + "Content-length: " + postBody.length() + "\r\n"
+ + HTTPSamplerBase.APPLICATION_X_WWW_FORM_URLENCODED + "\r\n"
+ + "Content-length: " + getBodyLength(postBody, contentEncoding) + "\r\n"
+ "\r\n"
+ postBody;
- s = getSamplerForRequest(TEST_POST_REQ, "UTF-8");
+ s = getSamplerForRequest(url, testPostRequest, contentEncoding);
assertEquals(HTTPSamplerBase.POST, s.getMethod());
assertFalse(s.getDoMultipartPost());
-
+ assertEquals(contentEncoding, s.getContentEncoding());
// Check arguments
arguments = s.getArguments();
assertEquals(13, arguments.getArgumentCount());
- checkArgument((HTTPArgument)arguments.getArgument(0), "update", "yes", "yes", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(1), "d", "1", "1", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(2), "d", "2", "2", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(3), "d", "", "", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(4), "d", "", "", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(5), "d", "", "", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(6), "d", "", "", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(7), "d", "", "", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(8), "d", "1", "1", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(9), "d", "2", "2", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(10), "d", "1", "1", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(11), "d", "", "", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(12), "d", "", "", "UTF-8", false);
+ checkArgument((HTTPArgument)arguments.getArgument(0), "update", "yes", "yes", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(1), "d", "1", "1", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(2), "d", "2", "2", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(3), "d", "", "", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(4), "d", "", "", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(5), "d", "", "", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(6), "d", "", "", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(7), "d", "", "", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(8), "d", "1", "1", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(9), "d", "2", "2", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(10), "d", "1", "1", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(11), "d", "", "", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(12), "d", "", "", contentEncoding, false);
// A HTTP POST request, with content-type text/plain
- TEST_POST_REQ = "POST http://localhost/matrix.html HTTP/1.0\n"
- + "Content-type: text/plain; charset=UTF-8\n"
+ contentEncoding = "UTF-8";
+ postBody = "update=yes&d=1&d=2&d=&d=&d=&d=&d=&d=1&d=2&d=1&d=\uc385&d=";
+ testPostRequest = "POST " + url + " HTTP/1.1\r\n"
+ + "Content-type: text/plain\r\n"
+ + "Content-length: " + getBodyLength(postBody, contentEncoding) + "\r\n"
+ + "\r\n"
+ postBody;
- s = getSamplerForRequest(TEST_POST_REQ, "UTF-8");
+ s = getSamplerForRequest(url, testPostRequest, contentEncoding);
assertEquals(HTTPSamplerBase.POST, s.getMethod());
assertFalse(s.getDoMultipartPost());
-
+ assertEquals(contentEncoding, s.getContentEncoding());
// Check arguments
// We should have one argument, with the value equal to the post body
arguments = s.getArguments();
assertEquals(1, arguments.getArgumentCount());
- checkArgument((HTTPArgument)arguments.getArgument(0), "", postBody, postBody, "UTF-8", false);
- }
+ checkArgument((HTTPArgument)arguments.getArgument(0), "", postBody, postBody, contentEncoding, false);
- // TODO: will need changing if arguments can be saved in decoded form
+ // A HTTP POST request, with content-type text/plain; charset=UTF-8
+ // The encoding should be picked up from the header we send with the request
+ contentEncoding = "UTF-8";
+ postBody = "update=yes&d=1&d=2&d=&d=&d=&d=&d=&d=1&d=2&d=1&d=\uc385&d=";
+ testPostRequest = "POST " + url + " HTTP/1.1\r\n"
+ + "Content-type: text/plain; charset=" + contentEncoding + "\r\n"
+ + "Content-length: " + getBodyLength(postBody, contentEncoding) + "\r\n"
+ + "\r\n"
+ + postBody;
+ // Use null for url to simulate that HttpRequestHdr do not
+ // know the encoding for the page. Specify contentEncoding, so the
+ // request is "sent" using that encoding
+ s = getSamplerForRequest(null, testPostRequest, contentEncoding);
+ assertEquals(HTTPSamplerBase.POST, s.getMethod());
+ assertFalse(s.getDoMultipartPost());
+ assertEquals(contentEncoding, s.getContentEncoding());
+ // Check arguments
+ // We should have one argument, with the value equal to the post body
+ arguments = s.getArguments();
+ assertEquals(1, arguments.getArgumentCount());
+ checkArgument((HTTPArgument)arguments.getArgument(0), "", postBody, postBody, contentEncoding, false);
+ }
+
public void testEncodedArguments() throws Exception {
- // A HTTP GET request
- String TEST_GET_REQ = "GET http://localhost:80/matrix.html"
- + "?abc"
- + "?SPACE=a+b"
- + "&space=a%20b"
- + "&query=What?"
- + " HTTP/1.1\n\n";
- HTTPSamplerBase s = getSamplerForRequest(TEST_GET_REQ, "UTF-8");
+ String url = "http://localhost/matrix.html";
+ // A HTTP GET request, with encoding not known
+ String contentEncoding = "";
+ String queryString = "abc%3FSPACE=a+b&space=a%20b&query=What%3F";
+ String testGetRequest = "GET " + url
+ + "?" + queryString
+ + " HTTP/1.1\r\n\r\n";
+ // Use null for url and contentEncoding, to simulate that HttpRequestHdr do not
+ // know the encoding for the page
+ HTTPSamplerBase s = getSamplerForRequest(null, testGetRequest, null);
assertEquals(HTTPSamplerBase.GET, s.getMethod());
+ assertEquals(queryString, s.getQueryString());
+ assertEquals(contentEncoding, s.getContentEncoding());
// Check arguments
Arguments arguments = s.getArguments();
assertEquals(3, arguments.getArgumentCount());
- checkArgument((HTTPArgument)arguments.getArgument(0), "abc?SPACE", "a+b", "a+b", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(1), "space", "a%20b", "a%20b", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(2), "query", "What?", "What?", "UTF-8", false);
+ // When the encoding is not known, the argument will get the encoded value, and the "encode?" set to false
+ checkArgument((HTTPArgument)arguments.getArgument(0), "abc%3FSPACE", "a+b", "a+b", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(1), "space", "a%20b", "a%20b", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(2), "query", "What%3F", "What%3F", contentEncoding, false);
+
+ // A HTTP GET request, with UTF-8 encoding
+ contentEncoding = "UTF-8";
+ queryString = "abc%3FSPACE=a+b&space=a%20b&query=What%3F";
+ testGetRequest = "GET " + url
+ + "?" + queryString
+ + " HTTP/1.1\r\n\r\n";
+ s = getSamplerForRequest(url, testGetRequest, contentEncoding);
+ assertEquals(HTTPSamplerBase.GET, s.getMethod());
+ String expectedQueryString = "abc%3FSPACE=a+b&space=a+b&query=What%3F";
+ assertEquals(expectedQueryString, s.getQueryString());
+ assertEquals(contentEncoding, s.getContentEncoding());
- // A HTTP POST request
- String postBody = "abc?SPACE=a+b&space=a%20b&query=What?";
- String TEST_POST_REQ = "POST http://localhost:80/matrix.html HTTP/1.1\n"
+ // Check arguments
+ arguments = s.getArguments();
+ assertEquals(3, arguments.getArgumentCount());
+ checkArgument((HTTPArgument)arguments.getArgument(0), "abc?SPACE", "a b", "a+b", contentEncoding, true);
+ checkArgument((HTTPArgument)arguments.getArgument(1), "space", "a b", "a+b", contentEncoding, true);
+ checkArgument((HTTPArgument)arguments.getArgument(2), "query", "What?", "What%3F", contentEncoding, true);
+
+ // A HTTP POST request, with unknown encoding
+ contentEncoding = "";
+ String postBody = "abc%3FSPACE=a+b&space=a%20b&query=What%3F";
+ String testPostRequest = "POST " + url + " HTTP/1.1\r\n"
+ "Content-type: "
- + HTTPSamplerBase.APPLICATION_X_WWW_FORM_URLENCODED
- + "; charset=UTF-8\n"
+ + HTTPSamplerBase.APPLICATION_X_WWW_FORM_URLENCODED + "\r\n"
+ + "Content-length: " + getBodyLength(postBody, contentEncoding) + "\r\n"
+ + "\r\n"
+ postBody;
- s = getSamplerForRequest(TEST_POST_REQ, "UTF-8");
+ // Use null for url and contentEncoding, to simulate that HttpRequestHdr do not
+ // know the encoding for the page
+ s = getSamplerForRequest(null, testPostRequest, null);
assertEquals(HTTPSamplerBase.POST, s.getMethod());
+ assertEquals(queryString, s.getQueryString());
+ assertEquals(contentEncoding, s.getContentEncoding());
assertFalse(s.getDoMultipartPost());
// Check arguments
arguments = s.getArguments();
assertEquals(3, arguments.getArgumentCount());
- checkArgument((HTTPArgument)arguments.getArgument(0), "abc?SPACE", "a+b", "a+b", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(1), "space", "a%20b", "a%20b", "UTF-8", false);
- checkArgument((HTTPArgument)arguments.getArgument(2), "query", "What?", "What?", "UTF-8", false);
+ // When the encoding is not known, the argument will get the encoded value, and the "encode?" set to false
+ checkArgument((HTTPArgument)arguments.getArgument(0), "abc%3FSPACE", "a+b", "a+b", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(1), "space", "a%20b", "a%20b", contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(2), "query", "What%3F", "What%3F", contentEncoding, false);
+
+ // A HTTP POST request, with UTF-8 encoding
+ contentEncoding = "UTF-8";
+ postBody = "abc?SPACE=a+b&space=a%20b&query=What?";
+ testPostRequest = "POST " + url + " HTTP/1.1\n"
+ + "Content-type: "
+ + HTTPSamplerBase.APPLICATION_X_WWW_FORM_URLENCODED + "\r\n"
+ + "Content-length: " + getBodyLength(postBody, contentEncoding) + "\r\n"
+ + "\r\n"
+ + postBody;
+ s = getSamplerForRequest(url, testPostRequest, contentEncoding);
+ assertEquals(HTTPSamplerBase.POST, s.getMethod());
+ expectedQueryString = "abc%3FSPACE=a+b&space=a+b&query=What%3F";
+ assertEquals(expectedQueryString, s.getQueryString());
+ assertEquals(contentEncoding, s.getContentEncoding());
+ assertFalse(s.getDoMultipartPost());
+
+ // Check arguments
+ arguments = s.getArguments();
+ assertEquals(3, arguments.getArgumentCount());
+ checkArgument((HTTPArgument)arguments.getArgument(0), "abc?SPACE", "a b", "a+b", contentEncoding, true);
+ checkArgument((HTTPArgument)arguments.getArgument(1), "space", "a b", "a+b", contentEncoding, true);
+ checkArgument((HTTPArgument)arguments.getArgument(2), "query", "What?", "What%3F", contentEncoding, true);
}
+ public void testGetRequestEncodings() throws Exception {
+ String url = "http://localhost/matrix.html";
+ // A HTTP GET request, with encoding not known
+ String contentEncoding = "";
+ String param1Value = "yes";
+ String param2Value = "0+5 -\u00c5\uc385%C3%85";
+ String param2ValueEncoded = URLEncoder.encode(param2Value);
+ String testGetRequest =
+ "GET " + url
+ + "?param1=" + param1Value + "¶m2=" + param2ValueEncoded + " "
+ + "HTTP/1.1\r\n\r\n";
+ // Use null for url and contentEncoding, to simulate that HttpRequestHdr do not
+ // know the encoding for the page
+ HTTPSamplerBase s = getSamplerForRequest(null, testGetRequest, null);
+ assertEquals(HTTPSamplerBase.GET, s.getMethod());
+ assertEquals(contentEncoding, s.getContentEncoding());
+ // Check arguments
+ Arguments arguments = s.getArguments();
+ assertEquals(2, arguments.getArgumentCount());
+ checkArgument((HTTPArgument)arguments.getArgument(0), "param1", param1Value, param1Value, contentEncoding, false);
+ // When the encoding is not known, the argument will get the encoded value, and the "encode?" set to false
+ checkArgument((HTTPArgument)arguments.getArgument(1), "param2", param2ValueEncoded, param2ValueEncoded, contentEncoding, false);
+
+ // A HTTP GET request, with UTF-8 encoding
+ contentEncoding = "UTF-8";
+ param1Value = "yes";
+ param2Value = "0+5 -\u007c\u2aa1\u266a\u0153\u20a1\u0115\u0364\u00c5\u2052\uc385%C3%85";
+ param2ValueEncoded = URLEncoder.encode(param2Value, contentEncoding);
+ testGetRequest =
+ "GET " + url
+ + "?param1=" + param1Value + "¶m2=" + param2ValueEncoded + " "
+ + "HTTP/1.1\r\n\r\n";
+ s = getSamplerForRequest(url, testGetRequest, contentEncoding);
+ assertEquals(HTTPSamplerBase.GET, s.getMethod());
+ assertEquals(contentEncoding, s.getContentEncoding());
+ // Check arguments
+ arguments = s.getArguments();
+ assertEquals(2, arguments.getArgumentCount());
+ checkArgument((HTTPArgument)arguments.getArgument(0), "param1", param1Value, param1Value, contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(1), "param2", param2Value, param2ValueEncoded, contentEncoding, true);
+
+ // A HTTP GET request, with ISO-8859-1 encoding
+ contentEncoding = "ISO-8859-1";
+ param1Value = "yes";
+ param2Value = "0+5 -\u00c5%C3%85";
+ param2ValueEncoded = URLEncoder.encode(param2Value, contentEncoding);
+ testGetRequest =
+ "GET " + url
+ + "?param1=" + param1Value + "¶m2=" + param2ValueEncoded + " "
+ + "HTTP/1.1\r\n\r\n";
+ s = getSamplerForRequest(url, testGetRequest, contentEncoding);
+ assertEquals(HTTPSamplerBase.GET, s.getMethod());
+ assertEquals(contentEncoding, s.getContentEncoding());
+ // Check arguments
+ arguments = s.getArguments();
+ assertEquals(2, arguments.getArgumentCount());
+ checkArgument((HTTPArgument)arguments.getArgument(0), "param1", param1Value, param1Value, contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(1), "param2", param2Value, param2ValueEncoded, contentEncoding, true);
+ }
+
+ public void testPostRequestEncodings() throws Exception {
+ String url = "http://localhost/matrix.html";
+ // A HTTP POST request, with encoding not known
+ String contentEncoding = "";
+ String param1Value = "yes";
+ String param2Value = "0+5 -\u00c5%C3%85";
+ String param2ValueEncoded = URLEncoder.encode(param2Value);
+ String postBody = "param1=" + param1Value + "¶m2=" + param2ValueEncoded + "\r\n";
+ String testPostRequest =
+ "POST " + url + " HTTP/1.1\r\n"
+ + "Content-type: "
+ + HTTPSamplerBase.APPLICATION_X_WWW_FORM_URLENCODED + "\r\n"
+ + "Content-length: " + getBodyLength(postBody, contentEncoding) + "\r\n"
+ + "\r\n"
+ + postBody;
+
+ // Use null for url and contentEncoding, to simulate that HttpRequestHdr do not
+ // know the encoding for the page
+ HTTPSamplerBase s = getSamplerForRequest(null, testPostRequest, null);
+ assertEquals(HTTPSamplerBase.POST, s.getMethod());
+ assertEquals(contentEncoding, s.getContentEncoding());
+ // Check arguments
+ Arguments arguments = s.getArguments();
+ assertEquals(2, arguments.getArgumentCount());
+ checkArgument((HTTPArgument)arguments.getArgument(0), "param1", param1Value, param1Value, contentEncoding, false);
+ // When the encoding is not known, the argument will get the encoded value, and the "encode?" set to false
+ checkArgument((HTTPArgument)arguments.getArgument(1), "param2", param2ValueEncoded, param2ValueEncoded, contentEncoding, false);
+
+ // A HTTP POST request, with UTF-8 encoding
+ contentEncoding = "UTF-8";
+ param1Value = "yes";
+ param2Value = "0+5 -\u007c\u2aa1\u266a\u0153\u20a1\u0115\u0364\u00c5\u2052\uc385%C3%85";
+ param2ValueEncoded = URLEncoder.encode(param2Value, contentEncoding);
+ postBody = "param1=" + param1Value + "¶m2=" + param2ValueEncoded + "\r\n";
+ testPostRequest =
+ "POST " + url + " HTTP/1.1\r\n"
+ + "Content-type: "
+ + HTTPSamplerBase.APPLICATION_X_WWW_FORM_URLENCODED + "\r\n"
+ + "Content-length: " + getBodyLength(postBody, contentEncoding) + "\r\n"
+ + "\r\n"
+ + postBody;
+
+ s = getSamplerForRequest(url, testPostRequest, contentEncoding);
+ assertEquals(HTTPSamplerBase.POST, s.getMethod());
+ assertEquals(contentEncoding, s.getContentEncoding());
+ // Check arguments
+ arguments = s.getArguments();
+ assertEquals(2, arguments.getArgumentCount());
+ checkArgument((HTTPArgument)arguments.getArgument(0), "param1", param1Value, param1Value, contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(1), "param2", param2Value, param2ValueEncoded, contentEncoding, true);
+
+ // A HTTP POST request, with ISO-8859-1 encoding
+ contentEncoding = "ISO-8859-1";
+ param1Value = "yes";
+ param2Value = "0+5 -\u00c5%C3%85";
+ param2ValueEncoded = URLEncoder.encode(param2Value, contentEncoding);
+ postBody = "param1=" + param1Value + "¶m2=" + param2ValueEncoded + "\r\n";
+ testPostRequest =
+ "POST " + url + " HTTP/1.1\r\n"
+ + "Content-type: "
+ + HTTPSamplerBase.APPLICATION_X_WWW_FORM_URLENCODED + "\r\n"
+ + "Content-length: " + getBodyLength(postBody, contentEncoding) + "\r\n"
+ + "\r\n"
+ + postBody;
+
+ s = getSamplerForRequest(url, testPostRequest, contentEncoding);
+ assertEquals(HTTPSamplerBase.POST, s.getMethod());
+ assertEquals(contentEncoding, s.getContentEncoding());
+ // Check arguments
+ arguments = s.getArguments();
+ assertEquals(2, arguments.getArgumentCount());
+ checkArgument((HTTPArgument)arguments.getArgument(0), "param1", param1Value, param1Value, contentEncoding, false);
+ checkArgument((HTTPArgument)arguments.getArgument(1), "param2", param2Value, param2ValueEncoded, contentEncoding, true);
+ }
+
public void testPostMultipartFormData() throws Exception {
+ String url = "http://localhost/matrix.html";
// A HTTP POST request, multipart/form-data, simple values,
String contentEncoding = "UTF-8";
String boundary = "xf8SqlDNvmn6mFYwrioJaeUR2_Z4cLRXOSmB";
@@ -147,10 +369,11 @@
String titleValue = "mytitle";
String descriptionValue = "mydescription";
String postBody = createMultipartFormBody(titleValue, descriptionValue, contentEncoding, true, boundary, endOfLine);
- String testPostRequest = createMultipartFormRequest(postBody, boundary, endOfLine);
+ String testPostRequest = createMultipartFormRequest(url, postBody, contentEncoding, boundary, endOfLine);
- HTTPSamplerBase s = getSamplerForRequest(testPostRequest, "UTF-8");
+ HTTPSamplerBase s = getSamplerForRequest(url, testPostRequest, contentEncoding);
assertEquals(HTTPSamplerBase.POST, s.getMethod());
+ assertEquals(contentEncoding, s.getContentEncoding());
assertTrue(s.getDoMultipartPost());
// Check arguments
@@ -166,10 +389,11 @@
titleValue = "mytitle";
descriptionValue = "mydescription";
postBody = createMultipartFormBody(titleValue, descriptionValue, contentEncoding, true, boundary, endOfLine);
- testPostRequest = createMultipartFormRequest(postBody, boundary, endOfLine);
+ testPostRequest = createMultipartFormRequest(url, postBody, contentEncoding, boundary, endOfLine);
- s = getSamplerForRequest(testPostRequest, "UTF-8");
+ s = getSamplerForRequest(url, testPostRequest, contentEncoding);
assertEquals(HTTPSamplerBase.POST, s.getMethod());
+ assertEquals(contentEncoding, s.getContentEncoding());
assertTrue(s.getDoMultipartPost());
// Check arguments
@@ -185,10 +409,11 @@
titleValue = "mytitle";
descriptionValue = "mydescription";
postBody = createMultipartFormBody(titleValue, descriptionValue, contentEncoding, true, boundary, endOfLine);
- testPostRequest = createMultipartFormRequest(postBody, boundary, endOfLine);
+ testPostRequest = createMultipartFormRequest(url, postBody, contentEncoding, boundary, endOfLine);
- s = getSamplerForRequest(testPostRequest, "UTF-8");
+ s = getSamplerForRequest(url, testPostRequest, contentEncoding);
assertEquals(HTTPSamplerBase.POST, s.getMethod());
+ assertEquals(contentEncoding, s.getContentEncoding());
assertTrue(s.getDoMultipartPost());
// Check arguments
@@ -204,10 +429,11 @@
titleValue = "/wEPDwULLTE2MzM2OTA0NTYPZBYCAgMPZ/rA+8DZ2dnZ2dnZ2d/GNDar6OshPwdJc=";
descriptionValue = "mydescription";
postBody = createMultipartFormBody(titleValue, descriptionValue, contentEncoding, true, boundary, endOfLine);
- testPostRequest = createMultipartFormRequest(postBody, boundary, endOfLine);
+ testPostRequest = createMultipartFormRequest(url, postBody, contentEncoding, boundary, endOfLine);
- s = getSamplerForRequest(testPostRequest, "UTF-8");
+ s = getSamplerForRequest(url, testPostRequest, contentEncoding);
assertEquals(HTTPSamplerBase.POST, s.getMethod());
+ assertEquals(contentEncoding, s.getContentEncoding());
assertTrue(s.getDoMultipartPost());
// Check arguments
@@ -218,7 +444,9 @@
}
public void testPostMultipartFileUpload() throws Exception {
+ String url = "http://localhost/matrix.html";
// A HTTP POST request, multipart/form-data, simple values,
+ String contentEncoding = "UTF-8";
String boundary = "xf8SqlDNvmn6mFYwrioJaeUR2_Z4cLRXOSmB";
String endOfLine = "\r\n";
String fileFieldValue = "test_file";
@@ -226,10 +454,12 @@
String mimeType = "text/plain";
String fileContent = "somedummycontent\n\ndfgdfg\r\nfgdgdg\nContent-type:dfsfsfds";
String postBody = createMultipartFileUploadBody(fileFieldValue, fileName, mimeType, fileContent, boundary, endOfLine);
- String testPostRequest = createMultipartFormRequest(postBody, boundary, endOfLine);
+ String testPostRequest = createMultipartFormRequest(url, postBody, contentEncoding, boundary, endOfLine);
- HTTPSamplerBase s = getSamplerForRequest(testPostRequest, "UTF-8");
+ HTTPSamplerBase s = getSamplerForRequest(url, testPostRequest, contentEncoding);
assertEquals(HTTPSamplerBase.POST, s.getMethod());
+ assertEquals(contentEncoding, s.getContentEncoding());
+ assertEquals("", s.getQueryString());
assertTrue(s.getDoMultipartPost());
// Check arguments
@@ -239,7 +469,7 @@
assertEquals(fileName, s.getFilename());
assertEquals(mimeType, s.getMimetype());
}
-
+
private String createMultipartFormBody(String titleValue, String descriptionValue, String contentEncoding, boolean includeExtraHeaders, String boundary, String endOfLine) {
// Title multipart
String postBody = "--" + boundary + endOfLine
@@ -276,24 +506,38 @@
return postBody;
}
- private String createMultipartFormRequest(String postBody, String boundary, String endOfLine) {
- String postRequest = "POST http://localhost:80/matrix.html HTTP/1.1" + endOfLine
+ private String createMultipartFormRequest(String url, String postBody, String contentEncoding, String boundary, String endOfLine)
+ throws IOException {
+ String postRequest = "POST " + url + " HTTP/1.1" + endOfLine
+ "Content-type: "
+ HTTPSamplerBase.MULTIPART_FORM_DATA
+ "; boundary=" + boundary + endOfLine
- + "Content-length: " + postBody.length() + endOfLine
+ + "Content-length: " + getBodyLength(postBody, contentEncoding) + endOfLine
+ endOfLine
+ postBody;
return postRequest;
}
- private HTTPSamplerBase getSamplerForRequest(String request, String contentEncoding)
+ private HTTPSamplerBase getSamplerForRequest(String url, String request, String contentEncoding)
throws IOException {
HttpRequestHdr req = new HttpRequestHdr();
- ByteArrayInputStream bis = new ByteArrayInputStream(request.getBytes(contentEncoding));
+ ByteArrayInputStream bis = null;
+ if(contentEncoding != null) {
+ bis = new ByteArrayInputStream(request.getBytes(contentEncoding));
+
+ }
+ else {
+ // Most browsers use ISO-8859-1 as default encoding, even if spec says UTF-8
+ bis = new ByteArrayInputStream(request.getBytes("ISO-8859-1"));
+ }
req.parse(bis);
bis.close();
- return req.getSampler();
+ Map pageEncodings = Collections.synchronizedMap(new HashMap());
+ Map formEncodings = Collections.synchronizedMap(new HashMap());
+ if(url != null && contentEncoding != null) {
+ pageEncodings.put(url, contentEncoding);
+ }
+ return req.getSampler(pageEncodings, formEncodings);
}
private void checkArgument(
@@ -304,8 +548,26 @@
String contentEncoding,
boolean expectedEncoded) throws IOException {
assertEquals(expectedName, arg.getName());
+// System.out.println("expect " + URLEncoder.encode(expectedValue, "UTF-8"));
+// System.out.println("actual " + URLEncoder.encode(arg.getValue(), "UTF-8"));
assertEquals(expectedValue, arg.getValue());
- assertEquals(expectedEncodedValue, arg.getEncodedValue(contentEncoding));
+ if(contentEncoding != null && contentEncoding.length() > 0) {
+ assertEquals(expectedEncodedValue, arg.getEncodedValue(contentEncoding));
+ }
+ else {
+ // Most browsers use ISO-8859-1 as default encoding, even if spec says UTF-8
+ assertEquals(expectedEncodedValue, arg.getEncodedValue("ISO-8859-1"));
+ }
assertEquals(expectedEncoded, arg.isAlwaysEncoded());
+ }
+
+ private int getBodyLength(String postBody, String contentEncoding) throws IOException {
+ if(contentEncoding != null && contentEncoding.length() > 0) {
+ return postBody.getBytes(contentEncoding).length;
+ }
+ else {
+ // Most browsers use ISO-8859-1 as default encoding, even if spec says UTF-8
+ return postBody.getBytes().length;
+ }
}
}
Modified: jakarta/jmeter/branches/rel-2-2/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jakarta/jmeter/branches/rel-2-2/xdocs/changes.xml?view=diff&rev=552959&r1=552958&r2=552959
==============================================================================
--- jakarta/jmeter/branches/rel-2-2/xdocs/changes.xml (original)
+++ jakarta/jmeter/branches/rel-2-2/xdocs/changes.xml Tue Jul 3 12:39:51 2007
@@ -38,7 +38,7 @@
<li>HttpClient options can be specified via httpclient.parameters file</li>
<li>HttpClient now behaves the same as Java Http for SSL certificates</li>
<li>HTTP Mirror Server to allow local testing of HTTP samplers</li>
-<li>HTTP Proxy supports XML-RPC recording</li>
+<li>HTTP Proxy supports XML-RPC recording, and other proxy improvements</li>
<li>__V() function allows support of nested variable references</li>
<li>LDAP Ext sampler optionally parses result sets and supports secure mode</li>
<li>FTP Sampler supports Ascii/Binary mode and upload</li>
@@ -145,6 +145,7 @@
<li>Bug 41880 - Add content-type filtering to HTTP Proxy Server</li>
<li>Bug 41876 - Add more options to control what the HTTP Proxy generates</li>
<li>Bug 42158 - Improve support for multipart/form-data requests in HTTP Proxy server</li>
+<li>Bug 42173 - Let HTTP Proxy handle encoding of request, and undecode parameter values</li>
<li>Bug 42674 - default to pre-emptive HTTP authorisation if not specified</li>
<li>Support "file" protocol in HTTP Samplers</li>
<li>Http Autoredirects are now enabled by default when creating new samplers</li>
---------------------------------------------------------------------
To unsubscribe, e-mail: jmeter-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jmeter-dev-help@jakarta.apache.org