You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@jakarta.apache.org by se...@apache.org on 2010/07/02 00:36:07 UTC
svn commit: r959801 - in /jakarta/jmeter/trunk:
src/protocol/http/org/apache/jmeter/protocol/http/sampler/
src/protocol/http/org/apache/jmeter/protocol/http/util/
test/src/org/apache/jmeter/protocol/http/util/ xdocs/ xdocs/usermanual/
Author: sebb
Date: Thu Jul 1 22:36:07 2010
New Revision: 959801
URL: http://svn.apache.org/viewvc?rev=959801&view=rev
Log:
Bug 49083 - collapse '/pathsegment/..' in redirect URLs
Modified:
jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/util/ConversionUtils.java
jakarta/jmeter/trunk/test/src/org/apache/jmeter/protocol/http/util/TestHTTPUtils.java
jakarta/jmeter/trunk/xdocs/changes.xml
jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml
Modified: jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java?rev=959801&r1=959800&r2=959801&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java (original)
+++ jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java Thu Jul 1 22:36:07 2010
@@ -204,7 +204,7 @@ public abstract class HTTPSamplerBase ex
private static final String RESPONSE_PARSERS= // list of parsers
JMeterUtils.getProperty("HTTPResponse.parsers");//$NON-NLS-1$
- static{
+ 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];
@@ -231,6 +231,10 @@ public abstract class HTTPSamplerBase ex
}
}
+ // Bug 49083
+ /** Whether to remove '/pathsegment/..' from redirects; default true */
+ private static boolean REMOVESLASHDOTDOT = JMeterUtils.getPropDefault("httpsampler.redirect.removeslashdotdot", true);
+
////////////////////// Variables //////////////////////
private boolean dynamicPath = false;// Set false if spaces are already encoded
@@ -1223,7 +1227,11 @@ public abstract class HTTPSamplerBase ex
// Browsers seem to tolerate Location headers with spaces,
// replacing them automatically with %20. We want to emulate
// this behaviour.
- String location = encodeSpaces(lastRes.getRedirectLocation());
+ String location = lastRes.getRedirectLocation();
+ if (REMOVESLASHDOTDOT) {
+ location = ConversionUtils.removeSlashDotDot(location);
+ }
+ location = encodeSpaces(location);
try {
lastRes = sample(ConversionUtils.makeRelativeURL(lastRes.getURL(), location), GET, true, frameDepth);
} catch (MalformedURLException e) {
Modified: jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/util/ConversionUtils.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/util/ConversionUtils.java?rev=959801&r1=959800&r2=959801&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/util/ConversionUtils.java (original)
+++ jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/util/ConversionUtils.java Thu Jul 1 22:36:07 2010
@@ -21,6 +21,9 @@ package org.apache.jmeter.protocol.http.
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -35,6 +38,11 @@ public class ConversionUtils {
private static final String CHARSET_EQ = "charset="; // $NON-NLS-1$
private static final int CHARSET_EQ_LEN = CHARSET_EQ.length();
+
+ private static final String SLASHDOTDOT = "/..";
+ private static final String DOTDOT = "..";
+ private static final String SLASH = "/";
+ private static final String COLONSLASHSLASH = "://";
/**
* Extract the encoding (charset) from the Content-Type,
@@ -85,6 +93,7 @@ public class ConversionUtils {
*/
public static URL makeRelativeURL(URL baseURL, String location) throws MalformedURLException{
URL initial = new URL(baseURL,location);
+
// skip expensive processing if it cannot apply
if (!location.startsWith("../")){// $NON-NLS-1$
return initial;
@@ -101,4 +110,116 @@ public class ConversionUtils {
}
return initial;
}
+
+ /**
+ * collapses absolute or relative URLs containing '/..' converting
+ * http://host/path1/../path2 to http://host/path2 or /one/two/../three to
+ * /one/three
+ *
+ * @param url
+ * @return collapsed URL
+ */
+ public static String removeSlashDotDot(String url)
+ {
+ if (url == null || (url = url.trim()).length() < 4 || !url.contains(SLASHDOTDOT))
+ {
+ return url;
+ }
+
+ /**
+ * http://auth@host:port/path1/path2/path3/?query#anchor
+ */
+
+ // get to 'path' part of the URL, preserving schema, auth, host if
+ // present
+
+ // find index of path start
+
+ int dotSlashSlashIndex = url.indexOf(COLONSLASHSLASH);
+ final int pathStartIndex;
+ if (dotSlashSlashIndex >= 0)
+ {
+ // absolute URL
+ pathStartIndex = url.indexOf(SLASH, dotSlashSlashIndex + COLONSLASHSLASH.length());
+ } else
+ {
+ // document or context-relative URL like:
+ // '/path/to'
+ // OR '../path/to'
+ // OR '/path/to/../path/'
+ pathStartIndex = 0;
+ }
+
+ // find path endIndex
+ int pathEndIndex = url.length();
+
+ int questionMarkIdx = url.indexOf('?');
+ if (questionMarkIdx > 0)
+ {
+ pathEndIndex = questionMarkIdx;
+ } else {
+ int anchorIdx = url.indexOf('#');
+ if (anchorIdx > 0)
+ {
+ pathEndIndex = anchorIdx;
+ }
+ }
+
+ // path is between idx='pathStartIndex' (inclusive) and
+ // idx='pathEndIndex' (exclusive)
+ String currentPath = url.substring(pathStartIndex, pathEndIndex);
+
+ final boolean startsWithSlash = currentPath.startsWith(SLASH);
+ final boolean endsWithSlash = currentPath.endsWith(SLASH);
+
+ StringTokenizer st = new StringTokenizer(currentPath, SLASH);
+ List<String> tokens = new ArrayList<String>();
+ while (st.hasMoreTokens())
+ {
+ tokens.add(st.nextToken());
+ }
+
+ for (int i = 0; i < tokens.size(); i++)
+ {
+ if (i < tokens.size() - 1)
+ {
+ final String thisToken = tokens.get(i);
+
+ // Verify for a ".." component at next iteration
+ if (thisToken.length() > 0 && !thisToken.equals(DOTDOT) && tokens.get(i + 1).equals(DOTDOT))
+ {
+ tokens.remove(i);
+ tokens.remove(i);
+ i = i - 2;
+ if (i < -1)
+ {
+ i = -1;
+ }
+ }
+ }
+
+ }
+
+ StringBuilder newPath = new StringBuilder();
+ if (startsWithSlash) {
+ newPath.append(SLASH);
+ }
+ for (int i = 0; i < tokens.size(); i++)
+ {
+ newPath.append(tokens.get(i));
+
+ // append '/' if this isn't the last token or it is but the original
+ // path terminated w/ a '/'
+ boolean appendSlash = i < (tokens.size() - 1) ? true : endsWithSlash;
+ if (appendSlash)
+ {
+ newPath.append(SLASH);
+ }
+ }
+
+ // install new path
+ StringBuilder s = new StringBuilder(url);
+ s.replace(pathStartIndex, pathEndIndex, newPath.toString());
+ return s.toString();
+ }
}
Modified: jakarta/jmeter/trunk/test/src/org/apache/jmeter/protocol/http/util/TestHTTPUtils.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/test/src/org/apache/jmeter/protocol/http/util/TestHTTPUtils.java?rev=959801&r1=959800&r2=959801&view=diff
==============================================================================
--- jakarta/jmeter/trunk/test/src/org/apache/jmeter/protocol/http/util/TestHTTPUtils.java (original)
+++ jakarta/jmeter/trunk/test/src/org/apache/jmeter/protocol/http/util/TestHTTPUtils.java Thu Jul 1 22:36:07 2010
@@ -59,4 +59,25 @@ public class TestHTTPUtils extends TestC
assertEquals(new URL("http://192.168.0.1/../d"),ConversionUtils.makeRelativeURL(base,"/../d"));
assertEquals(new URL("http://192.168.0.1/a/b/c/d"),ConversionUtils.makeRelativeURL(base,"./d"));
}
+
+ public void testRemoveSlashDotDot()
+ {
+ assertEquals("/path/", ConversionUtils.removeSlashDotDot("/path/"));
+ assertEquals("http://host/", ConversionUtils.removeSlashDotDot("http://host/"));
+ assertEquals("http://host/one", ConversionUtils.removeSlashDotDot("http://host/one"));
+ assertEquals("/two", ConversionUtils.removeSlashDotDot("/one/../two"));
+ assertEquals("http://host:8080/two", ConversionUtils.removeSlashDotDot("http://host:8080/one/../two"));
+ assertEquals("http://host:8080/two/", ConversionUtils.removeSlashDotDot("http://host:8080/one/../two/"));
+ assertEquals("http://usr@host:8080/two/", ConversionUtils.removeSlashDotDot("http://usr@host:8080/one/../two/"));
+ assertEquals("http://host:8080/two/?query#anchor", ConversionUtils.removeSlashDotDot("http://host:8080/one/../two/?query#anchor"));
+ assertEquals("one", ConversionUtils.removeSlashDotDot("one/two/.."));
+ assertEquals("../../path", ConversionUtils.removeSlashDotDot("../../path"));
+ assertEquals("/", ConversionUtils.removeSlashDotDot("/one/.."));
+ assertEquals("/", ConversionUtils.removeSlashDotDot("/one/../"));
+ assertEquals("/?a", ConversionUtils.removeSlashDotDot("/one/..?a"));
+ assertEquals("http://host/one", ConversionUtils.removeSlashDotDot("http://host/one/../one"));
+ assertEquals("http://host/one/two", ConversionUtils.removeSlashDotDot("http://host/one/two/../../one/two"));
+ assertEquals("http://host/..", ConversionUtils.removeSlashDotDot("http://host/.."));
+ assertEquals("http://host/../abc", ConversionUtils.removeSlashDotDot("http://host/../abc"));
+ }
}
Modified: jakarta/jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/changes.xml?rev=959801&r1=959800&r2=959801&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/changes.xml (original)
+++ jakarta/jmeter/trunk/xdocs/changes.xml Thu Jul 1 22:36:07 2010
@@ -161,6 +161,7 @@ This does not affect existing test plans
<li>Bug 48153 - Support for Cache-Control and Expires headers</li>
<li>Bug 47946 - Proxy should enable Grouping inside a Transaction Controller</li>
<li>Bug 48300 - Allow override of IP source address for HTTP HttpClient requests</li>
+<li>Bug 49083 - collapse '/pathsegment/..' in redirect URLs</li>
</ul>
<h3>Other samplers</h3>
Modified: jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=959801&r1=959800&r2=959801&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
+++ jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml Thu Jul 1 22:36:07 2010
@@ -197,6 +197,11 @@ https.default.protocol=SSLv3
Note that the HttpClient sampler may log the following message:<br/>
"Redirect requested but followRedirects is disabled"<br/>
This can be ignored.
+ <br/>
+ In versions after 2.3.4, JMeter will collapse paths of the form '/../segment' in
+ both absolute and relative URLs. For example http://host/one/../two => http://host/two.
+ If necessary, this behaviour can be suppressed by setting the JMeter property
+ <code>httpsampler.redirect.removeslashdotdot=false</code>
</property>
<property name="Use KeepAlive" required="Yes">JMeter sets the Connection: keep-alive header. This does not work properly with the default HTTP implementation, as connection re-use is not under user-control.
It does work with the Jakarta httpClient implementation.</property>
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@jakarta.apache.org
For additional commands, e-mail: notifications-help@jakarta.apache.org