Bug 558220 part 1. Add more debugging spew to the test HTTP server. r=waldo
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 28 Jun 2012 00:26:12 -0400
changeset 97841 4918f2685b05d574f84b90ef973e97dad7ce1542
parent 97838 bf8f2961d0cc0e48a6d21f67892a9f4743ddc9be
child 97842 72c50592b3a7d86bd0663d7ea06cde166a018d84
push id23001
push useremorley@mozilla.com
push dateThu, 28 Jun 2012 14:02:29 +0000
treeherdermozilla-central@9017b2970302 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswaldo
bugs558220
milestone16.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 558220 part 1. Add more debugging spew to the test HTTP server. r=waldo
netwerk/test/httpserver/httpd.js
--- a/netwerk/test/httpserver/httpd.js
+++ b/netwerk/test/httpserver/httpd.js
@@ -1605,25 +1605,31 @@ RequestReader.prototype =
     dumpn("*** _parseRequestLine('" + line + "')");
 
     var metadata = this._metadata;
 
     // clients and servers SHOULD accept any amount of SP or HT characters
     // between fields, even though only a single SP is required (section 19.3)
     var request = line.split(/[ \t]+/);
     if (!request || request.length != 3)
+    {
+      dumpn("*** No request in line");
       throw HTTP_400;
+    }
 
     metadata._method = request[0];
 
     // get the HTTP version
     var ver = request[2];
     var match = ver.match(/^HTTP\/(\d+\.\d+)$/);
     if (!match)
+    {
+      dumpn("*** No HTTP version in line");
       throw HTTP_400;
+    }
 
     // determine HTTP version
     try
     {
       metadata._httpVersion = new nsHttpVersion(match[1]);
       if (!metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_0))
         throw "unsupported HTTP version";
     }
@@ -1638,47 +1644,61 @@ RequestReader.prototype =
     var serverIdentity = this._connection.server.identity;
 
     var scheme, host, port;
 
     if (fullPath.charAt(0) != "/")
     {
       // No absolute paths in the request line in HTTP prior to 1.1
       if (!metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1))
+      {
+        dumpn("*** Metadata version too low");
         throw HTTP_400;
+      }
 
       try
       {
         var uri = Cc["@mozilla.org/network/io-service;1"]
                     .getService(Ci.nsIIOService)
                     .newURI(fullPath, null, null);
         fullPath = uri.path;
         scheme = uri.scheme;
         host = metadata._host = uri.asciiHost;
         port = uri.port;
         if (port === -1)
         {
           if (scheme === "http")
+          {
             port = 80;
+          }
           else if (scheme === "https")
+          {
             port = 443;
+          }
           else
+          {
+            dumpn("*** Unknown scheme: " + scheme);
             throw HTTP_400;
+          }
         }
       }
       catch (e)
       {
         // If the host is not a valid host on the server, the response MUST be a
         // 400 (Bad Request) error message (section 5.2).  Alternately, the URI
         // is malformed.
+        dumpn("*** Threw when dealing with URI: " + e);
         throw HTTP_400;
       }
 
       if (!serverIdentity.has(scheme, host, port) || fullPath.charAt(0) != "/")
+      {
+        dumpn("*** serverIdentity unknown or path does not start with '/'");
         throw HTTP_400;
+      }
     }
 
     var splitter = fullPath.indexOf("?");
     if (splitter < 0)
     {
       // _queryString already set in ctor
       metadata._path = fullPath;
     }
@@ -1712,45 +1732,48 @@ RequestReader.prototype =
 
     var headers = this._metadata._headers;
     var lastName = this._lastHeaderName;
     var lastVal = this._lastHeaderValue;
 
     var line = {};
     while (true)
     {
+      dumpn("*** Last name: '" + lastName + "'");
+      dumpn("*** Last val: '" + lastVal + "'");
       NS_ASSERT(!((lastVal === undefined) ^ (lastName === undefined)),
                 lastName === undefined ?
                   "lastVal without lastName?  lastVal: '" + lastVal + "'" :
                   "lastName without lastVal?  lastName: '" + lastName + "'");
 
       if (!data.readLine(line))
       {
         // save any data we have from the header we might still be processing
         this._lastHeaderName = lastName;
         this._lastHeaderValue = lastVal;
         return false;
       }
 
       var lineText = line.value;
+      dumpn("*** Line text: '" + lineText + "'");
       var firstChar = lineText.charAt(0);
 
       // blank line means end of headers
       if (lineText == "")
       {
         // we're finished with the previous header
         if (lastName)
         {
           try
           {
             headers.setHeader(lastName, lastVal, true);
           }
           catch (e)
           {
-            dumpn("*** e == " + e);
+            dumpn("*** setHeader threw on last header, e == " + e);
             throw HTTP_400;
           }
         }
         else
         {
           // no headers in request -- valid for HTTP/1.0 requests
         }
 
@@ -1758,17 +1781,17 @@ RequestReader.prototype =
         this._state = READER_IN_BODY;
         return true;
       }
       else if (firstChar == " " || firstChar == "\t")
       {
         // multi-line header if we've already seen a header line
         if (!lastName)
         {
-          // we don't have a header to continue!
+          dumpn("We don't have a header to continue!");
           throw HTTP_400;
         }
 
         // append this line's text to the value; starts with SP/HT, so no need
         // for separating whitespace
         lastVal += lineText;
       }
       else
@@ -1777,25 +1800,25 @@ RequestReader.prototype =
         if (lastName)
         {
           try
           {
             headers.setHeader(lastName, lastVal, true);
           }
           catch (e)
           {
-            dumpn("*** e == " + e);
+            dumpn("*** setHeader threw on a header, e == " + e);
             throw HTTP_400;
           }
         }
 
         var colon = lineText.indexOf(":"); // first colon must be splitter
         if (colon < 1)
         {
-          // no colon or missing header field-name
+          dumpn("*** No colon or missing header field-name");
           throw HTTP_400;
         }
 
         // set header name, value (to be set in the next loop, usually)
         lastName = lineText.substring(0, colon);
         lastVal = lineText.substring(colon + 1);
       } // empty, continuation, start of header
     } // while (true)
@@ -2522,26 +2545,32 @@ ServerHandler.prototype =
 
     var start, end;
     if (metadata._httpVersion.atLeast(nsHttpVersion.HTTP_1_1) &&
         metadata.hasHeader("Range") &&
         this._getTypeFromFile(file) !== SJS_TYPE)
     {
       var rangeMatch = metadata.getHeader("Range").match(/^bytes=(\d+)?-(\d+)?$/);
       if (!rangeMatch)
+      {
+        dumpn("*** Range header bogosity: '" + metadata.getHeader("Range") + "'");
         throw HTTP_400;
+      }
 
       if (rangeMatch[1] !== undefined)
         start = parseInt(rangeMatch[1], 10);
 
       if (rangeMatch[2] !== undefined)
         end = parseInt(rangeMatch[2], 10);
 
       if (start === undefined && end === undefined)
+      {
+        dumpn("*** More Range header bogosity: '" + metadata.getHeader("Range") + "'");
         throw HTTP_400;
+      }
 
       // No start given, so the end is really the count of bytes from the
       // end of the file.
       if (start === undefined)
       {
         start = Math.max(0, file.fileSize - end);
         end   = file.fileSize - 1;
       }
@@ -2946,16 +2975,17 @@ ServerHandler.prototype =
   {
     // decode and add underscores as necessary
     try
     {
       path = toInternalPath(path, true);
     }
     catch (e)
     {
+      dumpn("*** toInternalPath threw " + e);
       throw HTTP_400; // malformed path
     }
 
     // next, get the directory which contains this path
     var pathMap = this._pathDirectoryMap;
 
     // An example progression of tmp for a path "/foo/bar/baz/" might be:
     // "foo/bar/baz/", "foo/bar/baz", "foo/bar", "foo", ""
@@ -4637,17 +4667,20 @@ const headerUtils =
    *   if fieldName does not match the field-name production in RFC 2616
    * @returns string
    *   fieldName converted to lowercase if it is a valid header, for characters
    *   where case conversion is possible
    */
   normalizeFieldName: function(fieldName)
   {
     if (fieldName == "")
+    {
+      dumpn("*** Empty fieldName");
       throw Cr.NS_ERROR_INVALID_ARG;
+    }
 
     for (var i = 0, sz = fieldName.length; i < sz; i++)
     {
       if (!IS_TOKEN_ARRAY[fieldName.charCodeAt(i)])
       {
         dumpn(fieldName + " is not a valid header field name!");
         throw Cr.NS_ERROR_INVALID_ARG;
       }
@@ -4688,19 +4721,23 @@ const headerUtils =
     // SP before interpreting the field value or forwarding the message
     // downstream (section 4.2); we replace 1*LWS with a single SP
     var val = fieldValue.replace(/(?:(?:\r\n)?[ \t]+)+/g, " ");
 
     // remove leading/trailing LWS (which has been converted to SP)
     val = val.replace(/^ +/, "").replace(/ +$/, "");
 
     // that should have taken care of all CTLs, so val should contain no CTLs
+    dumpn("*** Normalized value: '" + val + "'");
     for (var i = 0, len = val.length; i < len; i++)
       if (isCTL(val.charCodeAt(i)))
+      {
+        dump("*** Char " + i + " has charcode " + val.charCodeAt(i));
         throw Cr.NS_ERROR_INVALID_ARG;
+      }
 
     // XXX disallows quoted-pair where CHAR is a CTL -- will not invalidly
     //     normalize, however, so this can be construed as a tightening of the
     //     spec and not entirely as a bug
     return val;
   }
 };