You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2013/05/28 12:53:41 UTC
svn commit: r1486861 -
/tomcat/trunk/test/org/apache/catalina/authenticator/TestFormAuthenticator.java
Author: markt
Date: Tue May 28 10:53:41 2013
New Revision: 1486861
URL: http://svn.apache.org/r1486861
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=54944
Enhancements to TestFormAuthenticator.
Patch by Brian Burch
Modified:
tomcat/trunk/test/org/apache/catalina/authenticator/TestFormAuthenticator.java
Modified: tomcat/trunk/test/org/apache/catalina/authenticator/TestFormAuthenticator.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/authenticator/TestFormAuthenticator.java?rev=1486861&r1=1486860&r2=1486861&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/authenticator/TestFormAuthenticator.java (original)
+++ tomcat/trunk/test/org/apache/catalina/authenticator/TestFormAuthenticator.java Tue May 28 10:53:41 2013
@@ -17,6 +17,8 @@
package org.apache.catalina.authenticator;
import java.io.File;
+import java.util.List;
+import java.util.StringTokenizer;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -24,92 +26,361 @@ import static org.junit.Assert.fail;
import org.junit.Test;
import org.apache.catalina.Context;
+import org.apache.catalina.Valve;
import org.apache.catalina.startup.SimpleHttpClient;
import org.apache.catalina.startup.TestTomcat.MapRealm;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.startup.TomcatBaseTest;
import org.apache.tomcat.websocket.server.WsListener;
+/*
+ * Test FORM authentication for sessions that do and do not use cookies.
+ *
+ * 1. A client that can accept and respond to a Set-Cookie for JSESSIONID
+ * will be able to maintain its authenticated session, no matter whether
+ * the session ID is changed once, many times, or not at all.
+ *
+ * 2. A client that cannot accept cookies will only be able to maintain a
+ * persistent session IF the server sends the correct (current) jsessionid
+ * as a path parameter appended to ALL urls within its response. That is
+ * achievable with servlets, jsps, jstl (all of which which can ask for an
+ * encoded url to be inserted into the dynamic web page). It cannot work
+ * with static html.
+ * note: this test class uses the tomcat somaple jsps, which conform.
+ *
+ * 3. Therefore, any webapp that MIGHT need to authenticate a client that
+ * does not accept cookies MUST generate EVERY protected resource url
+ * dynamically (so that it will include the current session ID).
+ *
+ * 4. Any webapp that cannot satify case 3 MUST turn off
+ * changeSessionIdOnAuthentication for its Context and thus degrade the
+ * session fixation protection for ALL of its clients.
+ * note from MarkT: Not sure I agree with this. If the URLs aren't
+ * being encoded, then the session is going to break regardless of
+ * whether or not the session ID changes.
+ *
+ * Unlike a "proper browser", this unit test class does a quite lot of
+ * screen-scraping and cheating of headers and urls (not very elegant,
+ * but it makes no claims to generality).
+ *
+ */
public class TestFormAuthenticator extends TomcatBaseTest {
+ // these should really be singletons to be type-safe,
+ // we are in a unit test and don't need to paranoid.
+ protected static final boolean USE_100_CONTINUE = true;
+ protected static final boolean NO_100_CONTINUE = !USE_100_CONTINUE;
+
+ protected static final boolean CLIENT_USE_COOKIES = true;
+ protected static final boolean CLIENT_NO_COOKIES = !CLIENT_USE_COOKIES;
+
+ protected static final boolean SERVER_USE_COOKIES = true;
+ protected static final boolean SERVER_NO_COOKIES = !SERVER_USE_COOKIES;
+
+ protected static final boolean SERVER_CHANGE_SESSID = true;
+ protected static final boolean SERVER_FREEZE_SESSID = !SERVER_CHANGE_SESSID;
+
+ // minimum session timeout
+ private static final int TIMEOUT_MINS = 1;
+ private static final long TIMEOUT_DELAY_MSECS =
+ (((TIMEOUT_MINS * 60) + 10) * 1000);
+
+ private FormAuthClient client;
+
+ // first, a set of tests where the server uses a cookie to carry
+ // the current session ID during and after authentication, and
+ // the client is prepared to return cookies with each request
+
@Test
- public void testGet() throws Exception {
- doTest("GET", "GET", false);
+ public void testGetWithCookies() throws Exception {
+ doTest("GET", "GET", NO_100_CONTINUE,
+ CLIENT_USE_COOKIES, SERVER_USE_COOKIES, SERVER_CHANGE_SESSID);
}
@Test
- public void testPostNoContinue() throws Exception {
- doTest("POST", "GET", false);
+ public void testPostNoContinueWithCookies() throws Exception {
+ doTest("POST", "GET", NO_100_CONTINUE,
+ CLIENT_USE_COOKIES, SERVER_USE_COOKIES, SERVER_CHANGE_SESSID);
}
@Test
- public void testPostWithContinue() throws Exception {
- doTest("POST", "GET", true);
+ public void testPostWithContinueAndCookies() throws Exception {
+ doTest("POST", "GET", USE_100_CONTINUE,
+ CLIENT_USE_COOKIES, SERVER_USE_COOKIES, SERVER_CHANGE_SESSID);
}
// Bug 49779
@Test
- public void testPostNoContinuePostRedirect() throws Exception {
- doTest("POST", "POST", false);
+ public void testPostNoContinuePostRedirectWithCookies() throws Exception {
+ doTest("POST", "POST", NO_100_CONTINUE,
+ CLIENT_USE_COOKIES, SERVER_USE_COOKIES, SERVER_CHANGE_SESSID);
}
// Bug 49779
@Test
- public void testPostWithContinuePostRedirect() throws Exception {
- doTest("POST", "POST", true);
+ public void testPostWithContinuePostRedirectWithCookies() throws Exception {
+ doTest("POST", "POST", USE_100_CONTINUE,
+ CLIENT_USE_COOKIES, SERVER_USE_COOKIES, SERVER_CHANGE_SESSID);
}
- private void doTest(String resourceMethod, String redirectMethod,
- boolean useContinue) throws Exception {
- FormAuthClient client = new FormAuthClient();
- // First request for authenticated resource
+ // next, a set of tests where the server Context is configured to never
+ // use cookies and the session ID is only carried as a url path parameter
+
+ // Bug 53584
+ @Test
+ public void testGetNoServerCookies() throws Exception {
+ doTest("GET", "GET", NO_100_CONTINUE,
+ CLIENT_NO_COOKIES, SERVER_NO_COOKIES, SERVER_CHANGE_SESSID);
+ }
+
+ @Test
+ public void testPostNoContinueNoServerCookies() throws Exception {
+ doTest("POST", "GET", NO_100_CONTINUE,
+ CLIENT_USE_COOKIES, SERVER_NO_COOKIES, SERVER_CHANGE_SESSID);
+ }
+
+ @Test
+ public void testPostWithContinueNoServerCookies() throws Exception {
+ doTest("POST", "GET", USE_100_CONTINUE,
+ CLIENT_USE_COOKIES, SERVER_NO_COOKIES, SERVER_CHANGE_SESSID);
+ }
+
+ // variant of Bug 49779
+ @Test
+ public void testPostNoContinuePostRedirectNoServerCookies()
+ throws Exception {
+ doTest("POST", "POST", NO_100_CONTINUE,
+ CLIENT_USE_COOKIES, SERVER_NO_COOKIES, SERVER_CHANGE_SESSID);
+ }
+
+ // variant of Bug 49779
+ @Test
+ public void testPostWithContinuePostRedirectNoServerCookies()
+ throws Exception {
+ doTest("POST", "POST", USE_100_CONTINUE,
+ CLIENT_USE_COOKIES, SERVER_NO_COOKIES, SERVER_CHANGE_SESSID);
+ }
+
+
+ // next, a set of tests where the server Context uses cookies,
+ // but the client refuses to return them and tries to use
+ // the session ID if carried as a url path parameter
+
+ @Test
+ public void testGetNoClientCookies() throws Exception {
+ doTest("GET", "GET", NO_100_CONTINUE,
+ CLIENT_NO_COOKIES, SERVER_USE_COOKIES, SERVER_CHANGE_SESSID);
+ }
+
+ @Test
+ public void testPostNoContinueNoClientCookies() throws Exception {
+ doTest("POST", "GET", NO_100_CONTINUE,
+ CLIENT_NO_COOKIES, SERVER_USE_COOKIES, SERVER_CHANGE_SESSID);
+ }
+
+ @Test
+ public void testPostWithContinueNoClientCookies() throws Exception {
+ doTest("POST", "GET", USE_100_CONTINUE,
+ CLIENT_NO_COOKIES, SERVER_USE_COOKIES, SERVER_CHANGE_SESSID);
+ }
+
+ // variant of Bug 49779
+ @Test
+ public void testPostNoContinuePostRedirectNoClientCookies()
+ throws Exception {
+ doTest("POST", "POST", NO_100_CONTINUE,
+ CLIENT_NO_COOKIES, SERVER_USE_COOKIES, SERVER_CHANGE_SESSID);
+ }
+
+ // variant of Bug 49779
+ @Test
+ public void testPostWithContinuePostRedirectNoClientCookies()
+ throws Exception {
+ doTest("POST", "POST", USE_100_CONTINUE,
+ CLIENT_NO_COOKIES, SERVER_USE_COOKIES, SERVER_CHANGE_SESSID);
+ }
+
+
+ // finally, a set of tests to explore quirky situations
+ // but there is not need to replicate all the scenarios above.
+
+ @Test
+ public void testNoChangedSessidWithCookies() throws Exception {
+ doTest("GET", "GET", NO_100_CONTINUE,
+ CLIENT_USE_COOKIES, SERVER_USE_COOKIES,
+ SERVER_FREEZE_SESSID);
+ }
+
+ @Test
+ public void testNoChangedSessidWithoutCookies() throws Exception {
+ doTest("GET", "GET", NO_100_CONTINUE,
+ CLIENT_NO_COOKIES, SERVER_USE_COOKIES,
+ SERVER_FREEZE_SESSID);
+ }
+
+ @Test
+ public void testTimeoutWithoutCookies() throws Exception {
+ String protectedUri = doTest("GET", "GET", NO_100_CONTINUE,
+ CLIENT_NO_COOKIES, SERVER_USE_COOKIES,
+ SERVER_FREEZE_SESSID);
+
+ // wait long enough for my session to expire
+ Thread.sleep(TIMEOUT_DELAY_MSECS);
+
+ // then try to continue using the expired session to get the
+ // protected resource once more.
+ // should get login challenge or timeout status 408
+ doTestProtected("GET", protectedUri, NO_100_CONTINUE,
+ FormAuthClient.LOGIN_REQUIRED, 1);
+ }
+
+ /*
+ * Choreograph the steps of the test dialogue with the server
+ * 1. while not authenticated, try to access a protected resource
+ * 2. respond to the login challenge with good credentials
+ * 3. after successful login, follow the redirect to the original page
+ * 4. repeatedly access the protected resource to demonstrate
+ * persistence of the authenticated session
+ *
+ * @param resourceMethod HTTP method for accessing the protected resource
+ * @param redirectMethod HTTP method for the login FORM reply
+ * @param useContinue whether the HTTP client should expect a 100 Continue
+ * @param clientShouldUseCookies whether the client should send cookies
+ * @param serverWillUseCookies whether the server should send cookies
+ *
+ */
+ private String doTest(String resourceMethod, String redirectMethod,
+ boolean useContinue, boolean clientShouldUseCookies,
+ boolean serverWillUseCookies, boolean serverWillChangeSessid)
+ throws Exception {
+
+ client = new FormAuthClient(clientShouldUseCookies,
+ serverWillUseCookies, serverWillChangeSessid);
+
+ // First request for protected resource gets the login page
client.setUseContinue(useContinue);
- client.doResourceRequest(resourceMethod);
+ client.doResourceRequest(resourceMethod, false, null, null);
assertTrue(client.isResponse200());
assertTrue(client.isResponseBodyOK());
+ String loginUri = client.extractBodyUri(
+ FormAuthClient.LOGIN_PARAM_TAG,
+ FormAuthClient.LOGIN_RESOURCE);
+ String originalSessionId = null;
+ if (serverWillUseCookies && clientShouldUseCookies) {
+ originalSessionId = client.getSessionId();
+ }
+ else {
+ originalSessionId = client.extractPathSessionId(loginUri);
+ }
client.reset();
- // Second request for the login page
+ // Second request replies to the login challenge
client.setUseContinue(useContinue);
- client.doLoginRequest();
- assertTrue(client.isResponse302());
+ client.doLoginRequest(loginUri);
+ assertTrue("login failed " + client.getResponseLine(),
+ client.isResponse302());
assertTrue(client.isResponseBodyOK());
+ String redirectUri = client.getRedirectUri();
client.reset();
- // Third request - follow the redirect
- client.doResourceRequest(redirectMethod);
+ // Third request - the login was successful so
+ // follow the redirect to the protected resource
+ client.doResourceRequest(redirectMethod, true, redirectUri, null);
if ("POST".equals(redirectMethod)) {
client.setUseContinue(useContinue);
}
assertTrue(client.isResponse200());
assertTrue(client.isResponseBodyOK());
+ String protectedUri = client.extractBodyUri(
+ FormAuthClient.RESOURCE_PARAM_TAG,
+ FormAuthClient.PROTECTED_RESOURCE);
+ String newSessionId = null;
+ if (serverWillUseCookies && clientShouldUseCookies) {
+ newSessionId = client.getSessionId();
+ }
+ else {
+ newSessionId = client.extractPathSessionId(protectedUri);
+ }
+ boolean sessionIdIsChanged = !(originalSessionId.equals(newSessionId));
+ assertTrue(sessionIdIsChanged == serverWillChangeSessid);
client.reset();
- // Subsequent requests - direct to the resource
- for (int i = 0; i < 5; i++) {
+ // Subsequent requests - keep accessing the protected resource
+ doTestProtected(resourceMethod, protectedUri, useContinue,
+ FormAuthClient.LOGIN_SUCCESSFUL, 5);
+
+ return protectedUri; // in case more requests will be issued
+ }
+
+ /*
+ * Repeatedly access the protected resource after the client has
+ * successfully logged-in to the webapp. The current session attributes
+ * will be used and cannot be changed.
+ * 3. after successful login, follow the redirect to the original page
+ * 4. repeatedly access the protected resource to demonstrate
+ * persistence of the authenticated session
+ *
+ * @param resourceMethod HTTP method for accessing the protected resource
+ * @param protectedUri to access (with or withour sessionid)
+ * @param useContinue whether the HTTP client should expect a 100 Continue
+ * @param clientShouldUseCookies whether the client should send cookies
+ * @param serverWillUseCookies whether the server should send cookies
+ *
+ */
+ private void doTestProtected(String resourceMethod, String protectedUri,
+ boolean useContinue, int phase, int repeatCount)
+ throws Exception {
+
+ // Subsequent requests - keep accessing the protected resource
+ for (int i = 0; i < repeatCount; i++) {
client.setUseContinue(useContinue);
- client.doResourceRequest(resourceMethod);
+ client.doResourceRequest(resourceMethod, false, protectedUri, null);
assertTrue(client.isResponse200());
- assertTrue(client.isResponseBodyOK());
+ assertTrue(client.isResponseBodyOK(phase));
client.reset();
}
}
+ /*
+ * Encapsulate the logic needed to run a suitably-configured tomcat
+ * instance, send it an HTTP request and process the server response
+ */
private final class FormAuthClient extends SimpleHttpClient {
- private static final String LOGIN_PAGE = "j_security_check";
-
- private String protectedPage = "index.jsp";
- private String protectedLocation = "/examples/jsp/security/protected/";
+ protected static final String LOGIN_PARAM_TAG = "action=";
+ protected static final String LOGIN_RESOURCE = "j_security_check";
+ protected static final String LOGIN_REPLY =
+ "j_username=tomcat&j_password=tomcat";
+
+ protected static final String PROTECTED_RELATIVE_PATH =
+ "/examples/jsp/security/protected/";
+ protected static final String PROTECTED_RESOURCE = "index.jsp";
+ private static final String PROTECTED_RESOURCE_URL =
+ PROTECTED_RELATIVE_PATH + PROTECTED_RESOURCE;
+ protected static final String RESOURCE_PARAM_TAG = "href=";
+ private static final char PARAM_DELIM = '?';
+
+ // primitive tracking of the test phases to verify the HTML body
+ protected static final int LOGIN_REQUIRED = 1;
+ protected static final int REDIRECTING = 2;
+ protected static final int LOGIN_SUCCESSFUL = 3;
private int requestCount = 0;
- private String sessionId = null;
- private FormAuthClient() throws Exception {
+ // todo: forgot this change and making it up again!
+ protected final String SESSION_PARAMETER_START =
+ SESSION_PARAMETER_NAME + "=";
+
+ private FormAuthClient(boolean clientShouldUseCookies,
+ boolean serverShouldUseCookies,
+ boolean serverShouldChangeSessid) throws Exception {
+
Tomcat tomcat = getTomcatInstance();
File appDir = new File(getBuildDirectory(), "webapps/examples");
Context ctx = tomcat.addWebapp(null, "/examples",
appDir.getAbsolutePath());
+ setUseCookies(clientShouldUseCookies);
+ ctx.setCookies(serverShouldUseCookies);
ctx.addApplicationListener(WsListener.class.getName());
MapRealm realm = new MapRealm();
@@ -119,108 +390,199 @@ public class TestFormAuthenticator exten
tomcat.start();
+ // perhaps this does not work until tomcat has started?
+ ctx.setSessionTimeout(TIMEOUT_MINS);
+
+ // Valve pipeline is only established after tomcat starts
+ Valve[] valves = ctx.getPipeline().getValves();
+ for (Valve valve : valves) {
+ if (valve instanceof AuthenticatorBase) {
+ ((AuthenticatorBase)valve)
+ .setChangeSessionIdOnAuthentication(
+ serverShouldChangeSessid);
+ break;
+ }
+ }
+
// Port only known after Tomcat starts
setPort(getPort());
}
- private void doResourceRequest(String method) throws Exception {
+ private void doLoginRequest(String loginUri) throws Exception {
+
+ doResourceRequest("POST", true,
+ PROTECTED_RELATIVE_PATH + loginUri, LOGIN_REPLY);
+ }
+
+ /*
+ * Prepare the resource request HTTP headers and issue the request.
+ * Three kinds of uri are supported:
+ * 1. fully qualified uri.
+ * 2. minimal uri without webapp path.
+ * 3. null - use the default protected resource
+ * Cookies are sent if available and supported by the test. Otherwise, the
+ * caller is expected to have provided a session id as a path parameter.
+ */
+ private void doResourceRequest(String method, boolean isFullQualUri,
+ String resourceUri, String requestTail) throws Exception {
+
+ // build the HTTP request while assembling the uri
StringBuilder requestHead = new StringBuilder(128);
- String requestTail;
- requestHead.append(method).append(" ").append(protectedLocation)
- .append(protectedPage);
- if ("GET".equals(method)) {
- requestHead.append("?role=bar");
+ requestHead.append(method).append(" ");
+ if (isFullQualUri) {
+ requestHead.append(resourceUri);
+ }
+ else {
+ if (resourceUri == null) {
+ // the default relative url
+ requestHead.append(PROTECTED_RESOURCE_URL);
+ }
+ else {
+ requestHead.append(PROTECTED_RELATIVE_PATH)
+ .append(resourceUri);
+ }
+ if ("GET".equals(method)) {
+ requestHead.append("?role=bar");
+ }
}
requestHead.append(" HTTP/1.1").append(CRLF);
+
+ // next, add the constant http headers
requestHead.append("Host: localhost").append(CRLF);
requestHead.append("Connection: close").append(CRLF);
+
+ // then any optional http headers
if (getUseContinue()) {
requestHead.append("Expect: 100-continue").append(CRLF);
}
- if (sessionId != null) {
- requestHead.append("Cookie: JSESSIONID=").append(sessionId)
- .append(CRLF);
+ if (getUseCookies()) {
+ String sessionId = getSessionId();
+ if (sessionId != null) {
+ requestHead.append("Cookie: ")
+ .append(SESSION_COOKIE_NAME)
+ .append("=").append(sessionId).append(CRLF);
+ }
}
+
+ // finally, for posts only, deal with the request content
if ("POST".equals(method)) {
+ if (requestTail == null) {
+ requestTail = "role=bar";
+ }
requestHead.append(
"Content-Type: application/x-www-form-urlencoded")
.append(CRLF);
- requestHead.append("Content-length: 8").append(CRLF);
- requestHead.append(CRLF);
- requestTail = "role=bar";
- } else {
- requestTail = CRLF;
+ // calculate post data length
+ String len = Integer.toString(requestTail.length());
+ requestHead.append("Content-length: ").append(len).append(CRLF);
}
- String request[] = new String[2];
- request[0] = requestHead.toString();
- request[1] = requestTail;
- doRequest(request);
- }
- private void doLoginRequest() throws Exception {
- StringBuilder requestHead = new StringBuilder(128);
- requestHead.append("POST ").append(protectedLocation)
- .append(LOGIN_PAGE).append(" HTTP/1.1").append(CRLF);
- requestHead.append("Host: localhost").append(CRLF);
- requestHead.append("Connection: close").append(CRLF);
- if (getUseContinue()) {
- requestHead.append("Expect: 100-continue").append(CRLF);
- }
- if (sessionId != null) {
- requestHead.append("Cookie: JSESSIONID=").append(sessionId)
- .append(CRLF);
- }
- requestHead.append(
- "Content-Type: application/x-www-form-urlencoded").append(
- CRLF);
- requestHead.append("Content-length: 35").append(CRLF);
+ // always put an empty line after the headers
requestHead.append(CRLF);
+
String request[] = new String[2];
request[0] = requestHead.toString();
- request[1] = "j_username=tomcat&j_password=tomcat";
-
+ request[1] = requestTail;
doRequest(request);
}
private void doRequest(String request[]) throws Exception {
setRequest(request);
-
connect();
processRequest();
- String newSessionId = getSessionId();
- if (newSessionId != null) {
- sessionId = newSessionId;
- }
disconnect();
-
requestCount++;
}
+ /*
+ * verify the server response html body is the page we expect,
+ * based on the dialogue position within doTest.
+ */
@Override
public boolean isResponseBodyOK() {
- if (requestCount == 1) {
- // First request should result in the login page
- assertContains(getResponseBody(),
- "<title>Login Page for Examples</title>");
- return true;
- } else if (requestCount == 2) {
- // Second request should result in a redirect
- return true;
- } else {
- // Subsequent requests should result in the protected page
- // The role parameter should have reached the page
- String body = getResponseBody();
- assertContains(body,
- "<title>Protected Page for Examples</title>");
- assertContains(body,
- "<input type=\"text\" name=\"role\" value=\"bar\"");
- return true;
+ return isResponseBodyOK(requestCount);
+ }
+
+ /*
+ * verify the server response html body is the page we expect,
+ * based on the dialogue position given by the caller.
+ */
+ public boolean isResponseBodyOK(int testPhase) {
+ switch (testPhase) {
+ case LOGIN_REQUIRED:
+ // First request should return in the login page
+ assertContains(getResponseBody(),
+ "<title>Login Page for Examples</title>");
+ return true;
+ case REDIRECTING:
+ // Second request should result in redirect without a body
+ return true;
+ default:
+ // Subsequent requests should return in the protected page.
+ // Our role parameter should be appear in the page.
+ String body = getResponseBody();
+ assertContains(body,
+ "<title>Protected Page for Examples</title>");
+ assertContains(body,
+ "<input type=\"text\" name=\"role\" value=\"bar\"");
+ return true;
+ }
+ }
+
+ /*
+ * Scan the server response body and extract the given
+ * url, including any path elements.
+ */
+ private String extractBodyUri(String paramTag, String resource) {
+ extractUriElements();
+ List<String> elements = getResponseBodyUriElements();
+ String fullPath = null;
+ for (String element : elements) {
+ int ix = element.indexOf(paramTag);
+ if (ix > -1) {
+ ix += paramTag.length();
+ char delim = element.charAt(ix);
+ int iy = element.indexOf(resource, ix);
+ if (iy > -1) {
+ int lastCharIx = element.indexOf(delim, iy);
+ fullPath = element.substring(iy, lastCharIx);
+ // remove any trailing parameters
+ int paramDelim = fullPath.indexOf(PARAM_DELIM);
+ if (paramDelim > -1) {
+ fullPath = fullPath.substring(0, paramDelim);
+ }
+ break;
+ }
+ }
+ }
+ return fullPath;
+ }
+
+ /*
+ * extract the session id path element (if it exists in the given url)
+ */
+ private String extractPathSessionId(String url) {
+ String sessionId = null;
+ int iStart = url.indexOf(SESSION_PARAMETER_START);
+ if (iStart > -1) {
+ iStart += SESSION_PARAMETER_START.length();
+ String remainder = url.substring(iStart);
+ StringTokenizer parser =
+ new StringTokenizer(remainder, SESSION_PATH_PARAMETER_TAILS);
+ if (parser.hasMoreElements()) {
+ sessionId = parser.nextToken();
+ }
+ else {
+ sessionId = url.substring(iStart);
}
}
+ return sessionId;
+ }
private void assertContains(String body, String expected) {
if (!body.contains(expected)) {
- fail("Response body check failure.\n"
+ fail("Response number " + requestCount
+ + ": body check failure.\n"
+ "Expected to contain substring: [" + expected
+ "]\nActual: [" + body + "]");
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org