You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2013/07/16 23:27:59 UTC

svn commit: r1503895 - in /subversion/branches/1.8.x: ./ subversion/libsvn_ra_serf/ subversion/libsvn_subr/ subversion/svn/

Author: breser
Date: Tue Jul 16 21:27:58 2013
New Revision: 1503895

URL: http://svn.apache.org/r1503895
Log:
Merge the 1.8.x-tristate-chunked-request branch:

 * r1502401, r1502674
   Implement the tristate version of http-chunked-request.
   Branch: ^/subversion/branches/1.8.x-tristate-chunked-request
   Justification:
     Better behavior over the boolean (see the mailing list for details)
   Notes:
     Revisions are actually from ^/subversion/branches/tristate-chunked-request
   Votes:
     +1: breser, danielsh, ivan, philip, rhuijben
     -0: gstein

Modified:
    subversion/branches/1.8.x/   (props changed)
    subversion/branches/1.8.x/configure.ac   (props changed)
    subversion/branches/1.8.x/subversion/libsvn_ra_serf/options.c
    subversion/branches/1.8.x/subversion/libsvn_ra_serf/ra_serf.h
    subversion/branches/1.8.x/subversion/libsvn_ra_serf/serf.c
    subversion/branches/1.8.x/subversion/libsvn_ra_serf/util.c
    subversion/branches/1.8.x/subversion/libsvn_subr/config_file.c
    subversion/branches/1.8.x/subversion/svn/svn.c   (props changed)

Propchange: subversion/branches/1.8.x/
------------------------------------------------------------------------------
  Merged /subversion/branches/tristate-chunked-request:r1502401,1502673
  Merged /subversion/trunk:r1489117,1496470,1497975,1497980,1498012,1499423,1499595,1502097
  Merged /subversion/branches/1.8.x-busted-proxy:r1499222-1502434
  Merged /subversion/branches/1.8.x-tristate-chunked-request:r1502435-1503894

Propchange: subversion/branches/1.8.x/configure.ac
------------------------------------------------------------------------------
  Merged /subversion/branches/1.8.x-busted-proxy/configure.ac:r1499222-1502434
  Merged /subversion/branches/1.8.x-tristate-chunked-request/configure.ac:r1502435-1503894

Modified: subversion/branches/1.8.x/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/libsvn_ra_serf/options.c?rev=1503895&r1=1503894&r2=1503895&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/branches/1.8.x/subversion/libsvn_ra_serf/options.c Tue Jul 16 21:27:58 2013
@@ -520,6 +520,65 @@ svn_ra_serf__exchange_capabilities(svn_r
 }
 
 
+static svn_error_t *
+create_simple_options_body(serf_bucket_t **body_bkt,
+                           void *baton,
+                           serf_bucket_alloc_t *alloc,
+                           apr_pool_t *pool)
+{
+  serf_bucket_t *body;
+  serf_bucket_t *s;
+
+  body = serf_bucket_aggregate_create(alloc);
+  svn_ra_serf__add_xml_header_buckets(body, alloc);
+
+  s = SERF_BUCKET_SIMPLE_STRING("<D:options xmlns:D=\"DAV:\" />", alloc);
+  serf_bucket_aggregate_append(body, s);
+
+  *body_bkt = body;
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_ra_serf__probe_proxy(svn_ra_serf__session_t *serf_sess,
+                         apr_pool_t *scratch_pool)
+{
+  svn_ra_serf__handler_t *handler;
+
+  handler = apr_pcalloc(scratch_pool, sizeof(*handler));
+  handler->handler_pool = scratch_pool;
+  handler->method = "OPTIONS";
+  handler->path = serf_sess->session_url.path;
+  handler->conn = serf_sess->conns[0];
+  handler->session = serf_sess;
+
+  /* We don't care about the response body, so discard it.  */
+  handler->response_handler = svn_ra_serf__handle_discard_body;
+
+  /* We need a simple body, in order to send it in chunked format.  */
+  handler->body_delegate = create_simple_options_body;
+
+  /* No special headers.  */
+
+  SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool));
+  /* Some versions of nginx in reverse proxy mode will return 411. They want
+     a Content-Length header, rather than chunked requests. We can keep other
+     HTTP/1.1 features, but will disable the chunking.  */
+  if (handler->sline.code == 411)
+    {
+      serf_sess->using_chunked_requests = FALSE;
+
+      return SVN_NO_ERROR;
+    }
+  SVN_ERR(svn_ra_serf__error_on_status(handler->sline,
+                                       handler->path,
+                                       handler->location));
+
+  return SVN_NO_ERROR;
+}
+
+
 svn_error_t *
 svn_ra_serf__has_capability(svn_ra_session_t *ra_session,
                             svn_boolean_t *has,

Modified: subversion/branches/1.8.x/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/libsvn_ra_serf/ra_serf.h?rev=1503895&r1=1503894&r2=1503895&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/1.8.x/subversion/libsvn_ra_serf/ra_serf.h Tue Jul 16 21:27:58 2013
@@ -144,6 +144,13 @@ struct svn_ra_serf__session_t {
      HTTP/1.0. Thus, we cannot send chunked requests.  */
   svn_boolean_t http10;
 
+  /* Should we use Transfer-Encoding: chunked for HTTP/1.1 servers. */
+  svn_boolean_t using_chunked_requests;
+
+  /* Do we need to detect whether the connection supports chunked requests?
+     i.e. is there a (reverse) proxy that does not support them?  */
+  svn_boolean_t detect_chunking;
+
   /* Our Version-Controlled-Configuration; may be NULL until we know it. */
   const char *vcc_url;
 
@@ -186,7 +193,7 @@ struct svn_ra_serf__session_t {
   const char *activity_collection_url;
 
   /* Are we using a proxy? */
-  int using_proxy;
+  svn_boolean_t using_proxy;
 
   const char *proxy_username;
   const char *proxy_password;
@@ -1334,6 +1341,14 @@ svn_ra_serf__run_merge(const svn_commit_
 
 /** OPTIONS-related functions **/
 
+/* When running with a proxy, we may need to detect and correct for problems.
+   This probing function will send a simple OPTIONS request to detect problems
+   with the connection.  */
+svn_error_t *
+svn_ra_serf__probe_proxy(svn_ra_serf__session_t *serf_sess,
+                         apr_pool_t *scratch_pool);
+
+
 /* On HTTPv2 connections, run an OPTIONS request over CONN to fetch the
    current youngest revnum, returning it in *YOUNGEST.
 

Modified: subversion/branches/1.8.x/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/libsvn_ra_serf/serf.c?rev=1503895&r1=1503894&r2=1503895&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/1.8.x/subversion/libsvn_ra_serf/serf.c Tue Jul 16 21:27:58 2013
@@ -137,6 +137,10 @@ load_http_auth_types(apr_pool_t *pool, s
    runtime configuration variable. */
 #define DEFAULT_HTTP_TIMEOUT 600
 
+/* Private symbol for the 1.9-public SVN_CONFIG_OPTION_HTTP_CHUNKED_REQUESTS */
+#define OPTION_HTTP_CHUNKED_REQUESTS "http-chunked-requests"
+
+
 static svn_error_t *
 load_config(svn_ra_serf__session_t *session,
             apr_hash_t *config_hash,
@@ -149,6 +153,7 @@ load_config(svn_ra_serf__session_t *sess
   const char *timeout_str = NULL;
   const char *exceptions;
   apr_port_t proxy_port;
+  svn_tristate_t chunked_requests;
 
   if (config_hash)
     {
@@ -225,6 +230,12 @@ load_config(svn_ra_serf__session_t *sess
                                SVN_CONFIG_OPTION_HTTP_MAX_CONNECTIONS,
                                SVN_CONFIG_DEFAULT_OPTION_HTTP_MAX_CONNECTIONS));
 
+  /* Should we use chunked transfer encoding. */ 
+  SVN_ERR(svn_config_get_tristate(config, &chunked_requests,
+                                  SVN_CONFIG_SECTION_GLOBAL,
+                                  OPTION_HTTP_CHUNKED_REQUESTS,
+                                  "auto", svn_tristate_unknown));
+
   if (config)
     server_group = svn_config_find_group(config,
                                          session->session_url.hostname,
@@ -281,6 +292,12 @@ load_config(svn_ra_serf__session_t *sess
                                    server_group,
                                    SVN_CONFIG_OPTION_HTTP_MAX_CONNECTIONS,
                                    session->max_connections));
+
+      /* Should we use chunked transfer encoding. */ 
+      SVN_ERR(svn_config_get_tristate(config, &chunked_requests,
+                                      server_group,
+                                      OPTION_HTTP_CHUNKED_REQUESTS,
+                                      "auto", chunked_requests));
     }
 
   /* Don't allow the http-max-connections value to be larger than our
@@ -355,6 +372,24 @@ load_config(svn_ra_serf__session_t *sess
       session->using_proxy = FALSE;
     }
 
+  /* Setup detect_chunking and using_chunked_requests based on
+   * the chunked_requests tristate */
+  if (chunked_requests == svn_tristate_unknown)
+    {
+      session->detect_chunking = TRUE;
+      session->using_chunked_requests = TRUE;
+    }
+  else if (chunked_requests == svn_tristate_true)
+    {
+      session->detect_chunking = FALSE;
+      session->using_chunked_requests = TRUE;
+    }
+  else /* chunked_requests == svn_tristate_false */
+    {
+      session->detect_chunking = FALSE;
+      session->using_chunked_requests = FALSE;
+    }
+
   /* Setup authentication. */
   SVN_ERR(load_http_auth_types(pool, config, server_group,
                                &session->authn_types));
@@ -442,6 +477,10 @@ svn_ra_serf__open(svn_ra_session_t *sess
      HTTP/1.1 is supported, we can upgrade. */
   serf_sess->http10 = TRUE;
 
+  /* If we switch to HTTP/1.1, then we will use chunked requests. We may disable
+     this, if we find an intervening proxy does not support chunked requests.  */
+  serf_sess->using_chunked_requests = TRUE;
+
   SVN_ERR(load_config(serf_sess, config, serf_sess->pool));
 
   serf_sess->conns[0] = apr_pcalloc(serf_sess->pool,
@@ -486,8 +525,17 @@ svn_ra_serf__open(svn_ra_session_t *sess
   if (err && err->apr_err == APR_EGENERAL)
     err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, err,
                             _("Connection to '%s' failed"), session_URL);
+  SVN_ERR(err);
 
-  return svn_error_trace(err);
+  /* We have set up a useful connection (that doesn't indication a redirect).
+     If we've been told there is possibly a worrisome proxy in our path to the
+     server AND we switched to HTTP/1.1 (chunked requests), then probe for
+     problems in any proxy.  */
+  if ((corrected_url == NULL || *corrected_url == NULL)
+      && serf_sess->detect_chunking && !serf_sess->http10)
+    SVN_ERR(svn_ra_serf__probe_proxy(serf_sess, pool));
+
+  return SVN_NO_ERROR;
 }
 
 /* Implements svn_ra__vtable_t.reparent(). */

Modified: subversion/branches/1.8.x/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/libsvn_ra_serf/util.c?rev=1503895&r1=1503894&r2=1503895&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/1.8.x/subversion/libsvn_ra_serf/util.c Tue Jul 16 21:27:58 2013
@@ -373,10 +373,8 @@ conn_setup(apr_socket_t *sock,
         {
           conn->ssl_context = serf_bucket_ssl_encrypt_context_get(*read_bkt);
 
-#if SERF_VERSION_AT_LEAST(1,0,0)
           serf_ssl_set_hostname(conn->ssl_context,
                                 conn->session->session_url.hostname);
-#endif
 
           serf_ssl_client_cert_provider_set(conn->ssl_context,
                                             svn_ra_serf__handle_client_cert,
@@ -642,10 +640,10 @@ setup_serf_req(serf_request_t *request,
 {
   serf_bucket_alloc_t *allocator = serf_request_get_alloc(request);
 
-#if SERF_VERSION_AT_LEAST(1, 1, 0)
   svn_spillbuf_t *buf;
+  svn_boolean_t set_CL = session->http10 || !session->using_chunked_requests;
 
-  if (session->http10 && body_bkt != NULL)
+  if (set_CL && 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
@@ -665,7 +663,6 @@ setup_serf_req(serf_request_t *request,
                                                request_pool,
                                                scratch_pool);
     }
-#endif
 
   /* Create a request bucket.  Note that this sucker is kind enough to
      add a "Host" header for us.  */
@@ -674,15 +671,13 @@ 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 SERF_VERSION_AT_LEAST(1, 1, 0)
-  if (session->http10)
+  if (set_CL)
     {
       if (body_bkt == NULL)
         serf_bucket_request_set_CL(*req_bkt, 0);
       else
         serf_bucket_request_set_CL(*req_bkt, svn_spillbuf__get_size(buf));
     }
-#endif
 
   *hdrs_bkt = serf_bucket_request_get_headers(*req_bkt);
 
@@ -696,10 +691,10 @@ setup_serf_req(serf_request_t *request,
       serf_bucket_headers_setn(*hdrs_bkt, "Content-Type", content_type);
     }
 
-#if SERF_VERSION_AT_LEAST(1, 1, 0)
   if (session->http10)
+    {
       serf_bucket_headers_setn(*hdrs_bkt, "Connection", "keep-alive");
-#endif
+    }
 
   if (accept_encoding)
     {
@@ -2418,8 +2413,10 @@ svn_ra_serf__error_on_status(serf_status
 
       case 411:
         return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
-                                _("DAV request failed: "
-                                  "Content length required"));
+                    _("DAV request failed: 411 Content length required. The "
+                      "server or an intermediate proxy does not accept "
+                      "chunked encoding. Try setting 'http-chunked-requests' "
+                      "to 'auto' or 'no' in your client configuration."));
     }
 
   if (sline.code >= 300)

Modified: subversion/branches/1.8.x/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/libsvn_subr/config_file.c?rev=1503895&r1=1503894&r2=1503895&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/1.8.x/subversion/libsvn_subr/config_file.c Tue Jul 16 21:27:58 2013
@@ -834,6 +834,8 @@ svn_config_ensure(const char *config_dir
         "###   http-max-connections       Maximum number of parallel server" NL
         "###                              connections to use for any given"  NL
         "###                              HTTP operation."                   NL
+        "###   http-chunked-requests      Whether to use chunked transfer"   NL
+        "###                              encoding for HTTP requests body."  NL
         "###   neon-debug-mask            Debug mask for Neon HTTP library"  NL
         "###   ssl-authority-files        List of files, each of a trusted CA"
                                                                              NL

Propchange: subversion/branches/1.8.x/subversion/svn/svn.c
------------------------------------------------------------------------------
  Merged /subversion/branches/1.8.x-tristate-chunked-request/subversion/svn/svn.c:r1502435-1503894
  Merged /subversion/trunk/subversion/svn/svn.c:r1488693,1489117,1490721,1491756,1491868,1494657,1495063,1495204,1495209,1495214,1495256,1495329,1495597,1495805,1495978,1496470,1497975,1497980,1498012,1498449,1498455,1498483-1498484,1498486,1498997,1499034,1499064,1499100,1499403,1499423,1499438,1499447,1499460,1499483,1499492,1499496,1499498,1499595,1500175,1500226,1500695,1500762,1500799,1500801-1500802,1500904,1500928,1502097
  Merged /subversion/branches/1.8.x-busted-proxy/subversion/svn/svn.c:r1499222-1502434
  Merged /subversion/branches/1.8.x-r1495063/subversion/svn/svn.c:r1495804-1501074