Author: ivan
Date: Fri Jun 21 12:47:46 2013
New Revision: 1495419

URL: http://svn.apache.org/r1495419
Log:
Rework server chunked transfer encoding support detection in ra_serf. Use 
HTTP/1.1 chunked transfer encoding for first OPTIONS request and then 
fallback to HTTP/1.0 requests if HTTP 411 status code or HTTP/1.0 response 
received.

Discussion and report: http://svn.haxx.se/dev/archive-2013-06/0408.shtml

* subversion/libsvn_ra_serf/ra_serf.h
  (svn_ra_serf__session_t): Remove HTTP10 and add USE_CHUNKED_ENCODING.
* subversion/libsvn_ra_serf/options.c
  (svn_ra_serf__exchange_capabilities): Retry OPTIONS request without using
   chunked transfer encoding if HTTP 411 status code or HTTP/1.0 response 
   received for chunked request.
* subversion/libsvn_ra_serf/serf.c
  (svn_ra_serf__open): Initialize USE_CHUNKED_ENCODING to TRUE.
* subversion/libsvn_ra_serf/util.c
  (setup_serf_req): Use USE_CHUNKED_ENCODING member instead of removed 
   HTTP10. Always send 'Connection: keep-alive' header.

Modified:
    subversion/trunk/subversion/libsvn_ra_serf/options.c
    subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
    subversion/trunk/subversion/libsvn_ra_serf/serf.c
    subversion/trunk/subversion/libsvn_ra_serf/util.c

Modified: subversion/trunk/subversion/libsvn_ra_serf/options.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/options.c?rev=1495419&r1=1495418&r2=1495419&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/options.c Fri Jun 21 12:47:46 
2013
@@ -488,6 +488,22 @@ svn_ra_serf__exchange_capabilities(svn_r
 
   err = svn_ra_serf__context_run_one(opt_ctx->handler, pool);
 
+  /* Retry request if HTTP/1.1 411 Length Required or we got HTTP/1.0 
response. */
+  if (serf_sess->use_chunked_encoding &&
+      (opt_ctx->handler->sline.code == 411 ||
+       opt_ctx->handler->sline.version == SERF_HTTP_10))
+    {
+      /* Ignore any errors and retry request using HTTP/1.0 with
+         Content-Length.*/
+      svn_error_clear(err);
+
+      serf_sess->use_chunked_encoding = FALSE;
+
+      SVN_ERR(create_options_req(&opt_ctx, serf_sess, serf_sess->conns[0], 
pool));
+
+      err = svn_ra_serf__context_run_one(opt_ctx->handler, pool);
+    }
+
   /* If our caller cares about server redirections, and our response
      carries such a thing, report as much.  We'll disregard ERR --
      it's most likely just a complaint about the response body not

Modified: subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h?rev=1495419&r1=1495418&r2=1495419&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h Fri Jun 21 12:47:46 
2013
@@ -140,9 +140,8 @@ struct svn_ra_serf__session_t {
   apr_uri_t repos_root;
   const char *repos_root_str;
 
-  /* The server is not Apache/mod_dav_svn (directly) and only supports
-     HTTP/1.0. Thus, we cannot send chunked requests.  */
-  svn_boolean_t http10;
+  /* The server supports chunked request bodies. */
+  svn_boolean_t use_chunked_encoding;
 
   /* Our Version-Controlled-Configuration; may be NULL until we know it. */
   const char *vcc_url;

Modified: subversion/trunk/subversion/libsvn_ra_serf/serf.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/serf.c?rev=1495419&r1=1495418&r2=1495419&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/serf.c Fri Jun 21 12:47:46 2013
@@ -437,9 +437,10 @@ svn_ra_serf__open(svn_ra_session_t *sess
 
   serf_sess->capabilities = apr_hash_make(serf_sess->pool);
 
-  /* We have to assume that the server only supports HTTP/1.0. Once it's clear
-     HTTP/1.1 is supported, we can upgrade. */
-  serf_sess->http10 = TRUE;
+  /* Assume HTTP/1.1 server and use chunked transfer encoding. We fallback
+   * to HTTP/1.0 requests in svn_ra_serf__exchange_capabilities() if server
+   * doesn't support chunked encoding. */
+  serf_sess->use_chunked_encoding = FALSE;
 
   SVN_ERR(load_config(serf_sess, config, serf_sess->pool));
 

Modified: subversion/trunk/subversion/libsvn_ra_serf/util.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/util.c?rev=1495419&r1=1495418&r2=1495419&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/util.c Fri Jun 21 12:47:46 2013
@@ -642,7 +642,7 @@ setup_serf_req(serf_request_t *request,
 
   svn_spillbuf_t *buf;
 
-  if (session->http10 && body_bkt != NULL)
+  if (!session->use_chunked_encoding && body_bkt != NULL)
     {
       /* Ugh. Use HTTP/1.0 to talk to the server because we don't know if
          it speaks HTTP/1.1 (and thus, chunked requests), or because the
@@ -670,7 +670,7 @@ setup_serf_req(serf_request_t *request,
 
   /* Set the Content-Length value. This will also trigger an HTTP/1.0
      request (rather than the default chunked request).  */
-  if (session->http10)
+  if (!session->use_chunked_encoding)
     {
       if (body_bkt == NULL)
         serf_bucket_request_set_CL(*req_bkt, 0);
@@ -690,10 +690,9 @@ setup_serf_req(serf_request_t *request,
       serf_bucket_headers_setn(*hdrs_bkt, "Content-Type", content_type);
     }
 
-  if (session->http10)
-    {
-      serf_bucket_headers_setn(*hdrs_bkt, "Connection", "keep-alive");
-    }
+  /* Always set Connection: keep-alive because we don't know if server
+   * is HTTP/1.1 aware. */
+  serf_bucket_headers_setn(*hdrs_bkt, "Connection", "keep-alive");
 
   if (accept_encoding)
     {
@@ -1861,10 +1860,6 @@ handle_response(serf_request_t *request,
 
       handler->sline = sl;
       handler->sline.reason = apr_pstrdup(handler->handler_pool, sl.reason);
-
-      /* HTTP/1.1? (or later)  */
-      if (sl.version != SERF_HTTP_10)
-        handler->session->http10 = FALSE;
     }
 
   /* Keep reading from the network until we've read all the headers.  */


Reply via email to