On Sat, Jun 29, 2013 at 5:17 AM, gstein_at_apache.org <gstein_at_apache.org> wrote:
> Author: gstein
> Date: Sat Jun 29 03:17:58 2013
> New Revision: 1497980
>
> URL: http://svn.apache.org/r1497980
> Log:
> Introduce dynamic detection proxies that cannot handle chunked requests.
>
> * subversion/libsvn_ra_serf/ra_serf.h:
> (svn_ra_serf__probe_proxy): new helper to determine proxy problems
>
> * subversion/libsvn_ra_serf/serf.c:
> (load_config): don't bother clearing USING_CHUNKED_REQUESTS. the
> probe (later) will deal with that.
> (svn_ra_serf__open): if we're potentially using a busted proxy, then
> probe the sucker
>
> * subversion/libsvn_ra_serf/options.c:
> (create_simple_options_body): a body delegate that constructs a
> small OPTIONS request body.
> (svn_ra_serf__probe_proxy): send a small OPTIONS request. toss the
> body. we're only looking for a 411 response.
>
> 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
>
> Modified: subversion/trunk/subversion/libsvn_ra_serf/options.c
> URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/options.c?rev=1497980&r1=1497979&r2=1497980&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/libsvn_ra_serf/options.c (original)
> +++ subversion/trunk/subversion/libsvn_ra_serf/options.c Sat Jun 29 03:17:58 2013
> @@ -518,6 +518,74 @@ 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;
> + svn_error_t *err;
> +
> + 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. */
> +
> + err = svn_ra_serf__context_run_one(handler, scratch_pool);
> + if (err)
> + {
> + /* 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;
> +
> + svn_error_clear(err);
> + return SVN_NO_ERROR;
> + }
> +
> + return svn_error_trace(
> + svn_error_compose_create(
> + svn_ra_serf__error_on_status(handler->sline,
> + serf_sess->session_url.path,
> + handler->location),
> + err));
> + }
> +
> + return SVN_NO_ERROR;
> +}
> +
> +
> svn_error_t *
> svn_ra_serf__has_capability(svn_ra_session_t *ra_session,
> svn_boolean_t *has,
>
> 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=1497980&r1=1497979&r2=1497980&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h (original)
> +++ subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h Sat Jun 29 03:17:58 2013
> @@ -1341,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/trunk/subversion/libsvn_ra_serf/serf.c
> URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/serf.c?rev=1497980&r1=1497979&r2=1497980&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/libsvn_ra_serf/serf.c (original)
> +++ subversion/trunk/subversion/libsvn_ra_serf/serf.c Sat Jun 29 03:17:58 2013
> @@ -368,12 +368,6 @@ load_config(svn_ra_serf__session_t *sess
> session->using_proxy = FALSE;
> }
>
> - /* If we're using a proxy, *and* it might be busted,
> - then disable chunked requests. */
> - /* ### we'll switch this to dynamic shortly. */
> - if (session->using_proxy && session->busted_proxy)
> - session->using_chunked_requests = FALSE;
> -
> /* Setup authentication. */
> SVN_ERR(load_http_auth_types(pool, config, server_group,
> &session->authn_types));
> @@ -509,8 +503,14 @@ 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);
> +
> + /* We have set up a useful connection. If we have a proxy AND it might be busted
> + AND we switched to HTTP/1.1 (chunked requests), then probe the proxy. */
> + if (serf_sess->using_proxy && serf_sess->busted_proxy && !serf_sess->http10)
> + SVN_ERR(svn_ra_serf__probe_proxy(serf_sess, pool));
This assumes the busted proxy is on the client's side, but that's not
necessary the case. I'd drop the first condition.
> - return svn_error_trace(err);
> + return SVN_NO_ERROR;
> }
>
> /* Implements svn_ra__vtable_t.reparent(). */
>
>
Missing from this patch is the instruction to the user to set the
busted-prody flag. I don't have a test setup so I can test it, but
from looking at the code it can be as simple as changing the error
text in svn_ra_serf__error_on_status.
Lieven
Received on 2013-06-29 09:09:15 CEST