bug 1128038 - h2 DAV methods set end_stream bit twice r=hurley a=sledru
authorPatrick McManus <mcmanus@ducksong.com>
Mon, 02 Feb 2015 13:42:23 -0500
changeset 243667 13fa209bd0b0
parent 243666 2e542912a7c0
child 243668 5c93fa7cc6d5
push id4431
push usermcmanus@ducksong.com
push date2015-02-04 14:19 +0000
treeherdermozilla-beta@13fa209bd0b0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershurley, sledru
bugs1128038
milestone36.0
bug 1128038 - h2 DAV methods set end_stream bit twice r=hurley a=sledru
netwerk/protocol/http/Http2Stream.cpp
netwerk/test/unit/test_http2.js
testing/xpcshell/moz-http2/moz-http2.js
--- a/netwerk/protocol/http/Http2Stream.cpp
+++ b/netwerk/protocol/http/Http2Stream.cpp
@@ -447,16 +447,21 @@ Http2Stream::ParseHttpRequestHeaders(con
   mSession->Compressor()->EncodeHeaderBlock(mFlatHttpRequestHeaders,
                                             head->Method(),
                                             head->RequestURI(),
                                             authorityHeader,
                                             scheme,
                                             head->IsConnect(),
                                             compressedData);
 
+  int64_t clVal = mSession->Compressor()->GetParsedContentLength();
+  if (clVal != -1) {
+    mRequestBodyLenRemaining = clVal;
+  }
+
   // Determine whether to put the fin bit on the header frame or whether
   // to wait for a data packet to put it on.
   uint8_t firstFrameFlags =  Http2Session::kFlag_PRIORITY;
 
   if (head->IsGet() ||
       head->IsHead()) {
     // for GET and HEAD place the fin bit right on the
     // header packet
@@ -550,52 +555,16 @@ Http2Stream::ParseHttpRequestHeaders(con
   Telemetry::Accumulate(Telemetry::SPDY_SYN_SIZE, compressedData.Length());
 
   // The size of the input headers is approximate
   uint32_t ratio =
     compressedData.Length() * 100 /
     (11 + head->RequestURI().Length() +
      mFlatHttpRequestHeaders.Length());
 
-  const char *beginBuffer = mFlatHttpRequestHeaders.BeginReading();
-  int32_t crlfIndex = mFlatHttpRequestHeaders.Find("\r\n");
-  while (true) {
-    int32_t startIndex = crlfIndex + 2;
-
-    crlfIndex = mFlatHttpRequestHeaders.Find("\r\n", false, startIndex);
-    if (crlfIndex == -1)
-      break;
-
-    int32_t colonIndex = mFlatHttpRequestHeaders.Find(":", false, startIndex,
-                                                      crlfIndex - startIndex);
-    if (colonIndex == -1)
-      break;
-
-    nsDependentCSubstring name = Substring(beginBuffer + startIndex,
-                                           beginBuffer + colonIndex);
-    // all header names are lower case in spdy
-    ToLowerCase(name);
-
-    if (name.EqualsLiteral("content-length")) {
-      nsCString *val = new nsCString();
-      int32_t valueIndex = colonIndex + 1;
-      while (valueIndex < crlfIndex && beginBuffer[valueIndex] == ' ')
-        ++valueIndex;
-
-      nsDependentCSubstring v = Substring(beginBuffer + valueIndex,
-                                          beginBuffer + crlfIndex);
-      val->Append(v);
-
-      int64_t len;
-      if (nsHttp::ParseInt64(val->get(), nullptr, &len))
-        mRequestBodyLenRemaining = len;
-      break;
-    }
-  }
-
   mFlatHttpRequestHeaders.Truncate();
   Telemetry::Accumulate(Telemetry::SPDY_SYN_RATIO, ratio);
   return NS_OK;
 }
 
 void
 Http2Stream::AdjustInitialWindow()
 {
--- a/netwerk/test/unit/test_http2.js
+++ b/netwerk/test/unit/test_http2.js
@@ -314,41 +314,48 @@ function test_http2_doubleheader() {
 // Make sure we handle GETs that cover more than 2 frames properly
 function test_http2_big() {
   var chan = makeChan("https://localhost:6944/big");
   var listener = new Http2BigListener();
   chan.asyncOpen(listener, null);
 }
 
 // Support for doing a POST
-function do_post(content, chan, listener) {
+function do_post(content, chan, listener, method) {
   var stream = Cc["@mozilla.org/io/string-input-stream;1"]
                .createInstance(Ci.nsIStringInputStream);
   stream.data = content;
 
   var uchan = chan.QueryInterface(Ci.nsIUploadChannel);
   uchan.setUploadStream(stream, "text/plain", stream.available());
 
-  chan.requestMethod = "POST";
+  chan.requestMethod = method;
 
   chan.asyncOpen(listener, null);
 }
 
 // Make sure we can do a simple POST
 function test_http2_post() {
   var chan = makeChan("https://localhost:6944/post");
   var listener = new Http2PostListener(md5s[0]);
-  do_post(posts[0], chan, listener);
+  do_post(posts[0], chan, listener, "POST");
+}
+
+// Make sure we can do a simple PATCH
+function test_http2_patch() {
+  var chan = makeChan("https://localhost:6944/patch");
+  var listener = new Http2PostListener(md5s[0]);
+  do_post(posts[0], chan, listener, "PATCH");
 }
 
 // Make sure we can do a POST that covers more than 2 frames
 function test_http2_post_big() {
   var chan = makeChan("https://localhost:6944/post");
   var listener = new Http2PostListener(md5s[1]);
-  do_post(posts[1], chan, listener);
+  do_post(posts[1], chan, listener, "POST");
 }
 
 Cu.import("resource://testing-common/httpd.js");
 var httpserv = null;
 var ios = Components.classes["@mozilla.org/network/io-service;1"]
                     .getService(Components.interfaces.nsIIOService);
 
 var altsvcClientListener = {
@@ -546,16 +553,17 @@ var tests = [ test_http2_post_big
 	    , test_http2_altsvc
             , test_http2_doubleheader
             , test_http2_xhr
             , test_http2_header
             , test_http2_cookie_crumbling
             , test_http2_multiplex
             , test_http2_big
             , test_http2_post
+            , test_http2_patch
             , test_http2_pushapi_1
             // These next two must always come in this order
             , test_http2_h11required_stream
             , test_http2_h11required_session
             , test_http2_retry_rst
             , test_http2_wrongsuite
 
             // cleanup
--- a/testing/xpcshell/moz-http2/moz-http2.js
+++ b/testing/xpcshell/moz-http2/moz-http2.js
@@ -222,18 +222,18 @@ function handleRequest(req, res) {
   else if (u.pathname === "/big") {
     content = generateContent(128 * 1024);
     var hash = crypto.createHash('md5');
     hash.update(content);
     var md5 = hash.digest('hex');
     res.setHeader("X-Expected-MD5", md5);
   }
 
-  else if (u.pathname === "/post") {
-    if (req.method != "POST") {
+  else if (u.pathname === "/post" || u.pathname === "/patch") {
+    if (req.method != "POST" && req.method != "PATCH") {
       res.writeHead(405);
       res.end('Unexpected method: ' + req.method);
       return;
     }
 
     var post_hash = crypto.createHash('md5');
     req.on('data', function receivePostData(chunk) {
       post_hash.update(chunk.toString());