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 2012/10/27 20:32:02 UTC

svn commit: r1402837 - /tomcat/trunk/test/org/apache/catalina/startup/SimpleHttpClient.java

Author: markt
Date: Sat Oct 27 18:32:02 2012
New Revision: 1402837

URL: http://svn.apache.org/viewvc?rev=1402837&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=53960
Extensions to HttpClient test helper class
Patch by Brian Burch

Modified:
    tomcat/trunk/test/org/apache/catalina/startup/SimpleHttpClient.java

Modified: tomcat/trunk/test/org/apache/catalina/startup/SimpleHttpClient.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/startup/SimpleHttpClient.java?rev=1402837&r1=1402836&r2=1402837&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/startup/SimpleHttpClient.java (original)
+++ tomcat/trunk/test/org/apache/catalina/startup/SimpleHttpClient.java Sat Oct 27 18:32:02 2012
@@ -39,7 +39,7 @@ import java.util.List;
  */
 public abstract class SimpleHttpClient {
     public static final String TEMP_DIR =
-        System.getProperty("java.io.tmpdir");
+            System.getProperty("java.io.tmpdir");
 
     public static final String CRLF = "\r\n";
 
@@ -48,13 +48,32 @@ public abstract class SimpleHttpClient {
     public static final String REDIRECT_302 = "HTTP/1.1 302";
     public static final String FAIL_400 = "HTTP/1.1 400";
     public static final String FAIL_404 = "HTTP/1.1 404";
+    public static final String TIMEOUT_408 = "HTTP/1.1 408";
     public static final String FAIL_413 = "HTTP/1.1 413";
     public static final String FAIL_50X = "HTTP/1.1 50";
     public static final String FAIL_500 = "HTTP/1.1 500";
     public static final String FAIL_501 = "HTTP/1.1 501";
 
+    private static final String CONTENT_LENGTH_HEADER_PREFIX =
+            "Content-Length: ";
+
+    protected static final String SESSION_COOKIE_NAME = "JSESSIONID";
+    protected static final String SESSION_PARAMETER_NAME =
+            SESSION_COOKIE_NAME.toLowerCase();
+
+    private static final String COOKIE_HEADER_PREFIX = "Set-Cookie: ";
     private static final String SESSION_COOKIE_HEADER_PREFIX =
-        "Set-Cookie: JSESSIONID=";
+            COOKIE_HEADER_PREFIX + SESSION_COOKIE_NAME + "=";
+
+    private static final String REDIRECT_HEADER_PREFIX = "Location: ";
+    protected static final String SESSION_PATH_PARAMETER_PREFIX =
+            SESSION_PARAMETER_NAME + "=";
+    protected static final String SESSION_PATH_PARAMETER_TAILS = CRLF + ";?";
+
+    private static final String ELEMENT_HEAD = "<";
+    private static final String ELEMENT_TAIL = ">";
+    private static final String RESOURCE_TAG = "a";
+    private static final String LOGIN_TAG = "form";
 
     private Socket socket;
     private Writer writer;
@@ -63,12 +82,18 @@ public abstract class SimpleHttpClient {
 
     private String[] request;
     private boolean useContinue = false;
+    private boolean useCookies = true;
     private int requestPause = 1000;
 
     private String responseLine;
     private List<String> responseHeaders = new ArrayList<>();
-    private String responseBody;
+    private String sessionId;
     private boolean useContentLength;
+    private int contentLength;
+    private String redirectUri;
+
+    private String responseBody;
+    private List<String> bodyUriElments = new ArrayList<>();
 
     protected void setPort(int thePort) {
         port = thePort;
@@ -86,6 +111,14 @@ public abstract class SimpleHttpClient {
         return useContinue;
     }
 
+    public void setUseCookies(boolean theUseCookiesFlag) {
+        useCookies = theUseCookiesFlag;
+    }
+
+    public boolean getUseCookies() {
+        return useCookies;
+    }
+
     public void setRequestPause(int theRequestPause) {
         requestPause = theRequestPause;
     }
@@ -106,18 +139,20 @@ public abstract class SimpleHttpClient {
         useContentLength = b;
     }
 
+    public void setSessionId(String theSessionId) {
+        sessionId = theSessionId;
+    }
+
     public String getSessionId() {
-        for (String header : responseHeaders) {
-            if (header.startsWith(SESSION_COOKIE_HEADER_PREFIX)) {
-                header = header.substring(SESSION_COOKIE_HEADER_PREFIX.length());
-                header = header.substring(0, header.indexOf(';'));
-                return header;
-            }
-        }
-        return null;
+        return sessionId;
+    }
+
+    public String getRedirectUri() {
+        return redirectUri;
     }
 
-    public void connect(int connectTimeout, int soTimeout) throws UnknownHostException, IOException {
+    public void connect(int connectTimeout, int soTimeout)
+           throws UnknownHostException, IOException {
         final String encoding = "ISO-8859-1";
         SocketAddress addr = new InetSocketAddress("localhost", port);
         socket = new Socket();
@@ -137,10 +172,11 @@ public abstract class SimpleHttpClient {
         processRequest(true);
     }
 
-    public void processRequest(boolean readBody) throws IOException, InterruptedException {
+    public void processRequest(boolean wantBody)
+            throws IOException, InterruptedException {
         sendRequest();
 
-        readResponse(readBody);
+        readResponse(wantBody);
 
     }
 
@@ -158,13 +194,13 @@ public abstract class SimpleHttpClient {
         }
     }
 
-    public void readResponse(boolean readBody) throws IOException {
-        // Reset fields use to hold response
-        responseLine = null;
+    public void readResponse(boolean wantBody) throws IOException {
+        // clear any residual data before starting on this response
         responseHeaders.clear();
         responseBody = null;
+        bodyUriElments.clear();
 
-        // Read the response
+        // Read the response status line
         responseLine = readLine();
 
         // Is a 100 continue response expected?
@@ -179,33 +215,114 @@ public abstract class SimpleHttpClient {
             }
         }
 
-        // Put the headers into the map
+        // Put the headers into a map, and process interesting ones
+        processHeaders();
+
+        // Read the body, if requested and if one exists
+        processBody(wantBody);
+
+        if (isResponse408()) {
+            // the session has timed out
+            sessionId = null;
+        }
+    }
+
+    /*
+     * Accumulate the response headers into a map, and extract
+     * interesting details at the same time
+     */
+    private void processHeaders() throws IOException {
+        // Reset response fields
+        redirectUri = null;
+        contentLength = -1;
+
         String line = readLine();
-        int cl = -1;
-        while (line!=null && line.length() > 0) {
+        while ((line != null) && (line.length() > 0)) {
             responseHeaders.add(line);
-            line = readLine();
-            if (line != null && line.startsWith("Content-Length: ")) {
-                cl = Integer.parseInt(line.substring(16));
+            if (line.startsWith(CONTENT_LENGTH_HEADER_PREFIX)) {
+                contentLength = Integer.parseInt(line.substring(16));
+            }
+            else if (line.startsWith(COOKIE_HEADER_PREFIX)) {
+                if (useCookies) {
+                    String temp = line.substring(
+                            SESSION_COOKIE_HEADER_PREFIX.length());
+                    temp = temp.substring(0, temp.indexOf(';'));
+                    setSessionId(temp);
+                }
+            }
+            else if (line.startsWith(REDIRECT_HEADER_PREFIX)) {
+                redirectUri = line.substring(REDIRECT_HEADER_PREFIX.length());
             }
+            line = readLine();
         }
+    }
 
-        // Read the body, if any
+    /*
+     * Read the body of the server response. Save its contents and
+     * search it for uri-elements only if requested
+     */
+    private void processBody(boolean wantBody) throws IOException {
+        // Read the body, if one exists
         StringBuilder builder = new StringBuilder();
-        if (readBody) {
-            if (cl > -1 && useContentLength) {
-                char[] body = new char[cl];
+        if (wantBody) {
+            if (useContentLength && (contentLength > -1)) {
+                char[] body = new char[contentLength];
                 reader.read(body);
                 builder.append(body);
-            } else {
-                line = readLine();
-                while (line != null) {
+            }
+            else {
+                // not using content length, so just read it line by line
+                String line = null;
+                while ((line = readLine()) != null) {
                     builder.append(line);
-                    line = readLine();
                 }
             }
         }
         responseBody = builder.toString();
+        extractUriElements(responseBody);
+    }
+
+    /*
+     * Scan an html body for useful html uri elements. If any are found,
+     * then accumulate them. Test classes might not use them, but they
+     * are collected anyway.
+     */
+    private void extractUriElements(String body) {
+        if (body.length() > 0) {
+            int ix = 0;
+            while ((ix = extractUriElement(body, ix, RESOURCE_TAG)) > 0){}
+            ix = 0;
+            while ((ix = extractUriElement(body, ix, LOGIN_TAG)) > 0){}
+        }
+    }
+
+    /*
+     * Scan an html body for a given html uri element, starting from the
+     * given index into the source string. If any are found, simply
+     * accumulate them as literal strings, including angle brackets.
+     * note: nested elements will not be collected.
+     *
+     * @param body HTTP body of the response
+     * @param startIx offset into the body to resume the scan (for iteration)
+     * @param elementName to scan for (only one at a time)
+     * @returns the index into the body to continue the scan (for iteration)
+     */
+    private int extractUriElement(String body, int startIx, String elementName) {
+        String detector = ELEMENT_HEAD + elementName + " ";
+        int iStart = body.indexOf(detector, startIx);
+        if (iStart > -1) {
+            int iEnd = body.indexOf(ELEMENT_TAIL, iStart);
+            if (iEnd < 0) {
+                throw new IllegalArgumentException(
+                        "Response body check failure.\n"
+                        + "element [" + detector + "] is not terminated with ["
+                        + ELEMENT_TAIL + "]\nActual: [" + body + "]");
+            }
+            String element = body.substring(iStart, iEnd);
+            bodyUriElments.add(element);
+            iStart += element.length();
+        }
+        return iStart;
     }
 
     public String readLine() throws IOException {
@@ -253,6 +370,10 @@ public abstract class SimpleHttpClient {
         return getResponseLine().startsWith(FAIL_404);
     }
 
+    public boolean isResponse408() {
+        return getResponseLine().startsWith(TIMEOUT_408);
+    }
+
     public boolean isResponse413() {
         return getResponseLine().startsWith(FAIL_413);
     }



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org