aboutsummaryrefslogtreecommitdiff
path: root/subversion/libsvn_ra_serf
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_ra_serf')
-rw-r--r--subversion/libsvn_ra_serf/blame.c2
-rw-r--r--subversion/libsvn_ra_serf/commit.c6
-rw-r--r--subversion/libsvn_ra_serf/getdate.c13
-rw-r--r--subversion/libsvn_ra_serf/getlocations.c2
-rw-r--r--subversion/libsvn_ra_serf/getlocationsegments.c2
-rw-r--r--subversion/libsvn_ra_serf/getlocks.c2
-rw-r--r--subversion/libsvn_ra_serf/inherited_props.c2
-rw-r--r--subversion/libsvn_ra_serf/log.c2
-rw-r--r--subversion/libsvn_ra_serf/mergeinfo.c15
-rw-r--r--subversion/libsvn_ra_serf/options.c68
-rw-r--r--subversion/libsvn_ra_serf/property.c2
-rw-r--r--subversion/libsvn_ra_serf/ra_serf.h19
-rw-r--r--subversion/libsvn_ra_serf/replay.c4
-rw-r--r--subversion/libsvn_ra_serf/serf.c58
-rw-r--r--subversion/libsvn_ra_serf/update.c6
-rw-r--r--subversion/libsvn_ra_serf/util.c35
-rw-r--r--subversion/libsvn_ra_serf/xml.c8
17 files changed, 200 insertions, 46 deletions
diff --git a/subversion/libsvn_ra_serf/blame.c b/subversion/libsvn_ra_serf/blame.c
index fa4243c0840b..b6f136a2bdad 100644
--- a/subversion/libsvn_ra_serf/blame.c
+++ b/subversion/libsvn_ra_serf/blame.c
@@ -366,7 +366,7 @@ svn_ra_serf__get_file_revs(svn_ra_session_t *ra_session,
err = svn_ra_serf__context_run_one(handler, pool);
err = svn_error_compose_create(
- svn_ra_serf__error_on_status(handler->sline.code,
+ svn_ra_serf__error_on_status(handler->sline,
handler->path,
handler->location),
err);
diff --git a/subversion/libsvn_ra_serf/commit.c b/subversion/libsvn_ra_serf/commit.c
index aaf17177d9d4..56a2bcea1e3b 100644
--- a/subversion/libsvn_ra_serf/commit.c
+++ b/subversion/libsvn_ra_serf/commit.c
@@ -223,7 +223,7 @@ return_response_err(svn_ra_serf__handler_t *handler)
/* Try to return one of the standard errors for 301, 404, etc.,
then look for an error embedded in the response. */
return svn_error_compose_create(svn_ra_serf__error_on_status(
- handler->sline.code,
+ handler->sline,
handler->path,
handler->location),
err);
@@ -2269,7 +2269,9 @@ abort_edit(void *edit_baton,
&& handler->sline.code != 404
)
{
- SVN_ERR_MALFUNCTION();
+ return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+ _("DELETE returned unexpected status: %d"),
+ handler->sline.code);
}
return SVN_NO_ERROR;
diff --git a/subversion/libsvn_ra_serf/getdate.c b/subversion/libsvn_ra_serf/getdate.c
index 867e86fbd501..cc1014ef0297 100644
--- a/subversion/libsvn_ra_serf/getdate.c
+++ b/subversion/libsvn_ra_serf/getdate.c
@@ -131,6 +131,7 @@ svn_ra_serf__get_dated_revision(svn_ra_session_t *ra_session,
svn_ra_serf__handler_t *handler;
svn_ra_serf__xml_context_t *xmlctx;
const char *report_target;
+ svn_error_t *err;
date_ctx = apr_palloc(pool, sizeof(*date_ctx));
date_ctx->time = tm;
@@ -155,7 +156,15 @@ svn_ra_serf__get_dated_revision(svn_ra_session_t *ra_session,
*date_ctx->revision = SVN_INVALID_REVNUM;
- /* ### use svn_ra_serf__error_on_status() ? */
+ err = svn_ra_serf__context_run_one(handler, pool);
- return svn_error_trace(svn_ra_serf__context_run_one(handler, pool));
+ SVN_ERR(svn_error_compose_create(
+ svn_ra_serf__error_on_status(handler->sline,
+ report_target,
+ handler->location),
+ err));
+
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(*revision));
+
+ return SVN_NO_ERROR;
}
diff --git a/subversion/libsvn_ra_serf/getlocations.c b/subversion/libsvn_ra_serf/getlocations.c
index d3e3175fac3d..1ae4f82dd8c8 100644
--- a/subversion/libsvn_ra_serf/getlocations.c
+++ b/subversion/libsvn_ra_serf/getlocations.c
@@ -192,7 +192,7 @@ svn_ra_serf__get_locations(svn_ra_session_t *ra_session,
err = svn_ra_serf__context_run_one(handler, pool);
SVN_ERR(svn_error_compose_create(
- svn_ra_serf__error_on_status(handler->sline.code,
+ svn_ra_serf__error_on_status(handler->sline,
req_url,
handler->location),
err));
diff --git a/subversion/libsvn_ra_serf/getlocationsegments.c b/subversion/libsvn_ra_serf/getlocationsegments.c
index d2b69bf685c4..e5c58a90b5a7 100644
--- a/subversion/libsvn_ra_serf/getlocationsegments.c
+++ b/subversion/libsvn_ra_serf/getlocationsegments.c
@@ -194,7 +194,7 @@ svn_ra_serf__get_location_segments(svn_ra_session_t *ra_session,
err = svn_ra_serf__context_run_one(handler, pool);
err = svn_error_compose_create(
- svn_ra_serf__error_on_status(handler->sline.code,
+ svn_ra_serf__error_on_status(handler->sline,
handler->path,
handler->location),
err);
diff --git a/subversion/libsvn_ra_serf/getlocks.c b/subversion/libsvn_ra_serf/getlocks.c
index 61b8b8c7b051..04e556179936 100644
--- a/subversion/libsvn_ra_serf/getlocks.c
+++ b/subversion/libsvn_ra_serf/getlocks.c
@@ -266,7 +266,7 @@ svn_ra_serf__get_locks(svn_ra_session_t *ra_session,
have existed earlier (E.g. 'svn ls http://s/svn/trunk/file@1' */
if (handler->sline.code != 404)
{
- SVN_ERR(svn_ra_serf__error_on_status(handler->sline.code,
+ SVN_ERR(svn_ra_serf__error_on_status(handler->sline,
handler->path,
handler->location));
}
diff --git a/subversion/libsvn_ra_serf/inherited_props.c b/subversion/libsvn_ra_serf/inherited_props.c
index 9283a5a53005..54eae0b5be7c 100644
--- a/subversion/libsvn_ra_serf/inherited_props.c
+++ b/subversion/libsvn_ra_serf/inherited_props.c
@@ -332,7 +332,7 @@ svn_ra_serf__get_inherited_props(svn_ra_session_t *ra_session,
err = svn_ra_serf__context_run_one(handler, scratch_pool);
SVN_ERR(svn_error_compose_create(
- svn_ra_serf__error_on_status(handler->sline.code,
+ svn_ra_serf__error_on_status(handler->sline,
handler->path,
handler->location),
err));
diff --git a/subversion/libsvn_ra_serf/log.c b/subversion/libsvn_ra_serf/log.c
index e44753b07ae6..58a57d890ee4 100644
--- a/subversion/libsvn_ra_serf/log.c
+++ b/subversion/libsvn_ra_serf/log.c
@@ -595,7 +595,7 @@ svn_ra_serf__get_log(svn_ra_session_t *ra_session,
err = svn_ra_serf__context_run_one(handler, pool);
SVN_ERR(svn_error_compose_create(
- svn_ra_serf__error_on_status(handler->sline.code,
+ svn_ra_serf__error_on_status(handler->sline,
req_url,
handler->location),
err));
diff --git a/subversion/libsvn_ra_serf/mergeinfo.c b/subversion/libsvn_ra_serf/mergeinfo.c
index b0bf8337cdfd..bd4fcbab5e7b 100644
--- a/subversion/libsvn_ra_serf/mergeinfo.c
+++ b/subversion/libsvn_ra_serf/mergeinfo.c
@@ -191,7 +191,7 @@ svn_ra_serf__get_mergeinfo(svn_ra_session_t *ra_session,
svn_boolean_t include_descendants,
apr_pool_t *pool)
{
- svn_error_t *err, *err2;
+ svn_error_t *err;
mergeinfo_context_t *mergeinfo_ctx;
svn_ra_serf__session_t *session = ra_session->priv;
svn_ra_serf__handler_t *handler;
@@ -229,15 +229,10 @@ svn_ra_serf__get_mergeinfo(svn_ra_session_t *ra_session,
err = svn_ra_serf__context_run_one(handler, pool);
- err2 = svn_ra_serf__error_on_status(handler->sline.code, handler->path,
- handler->location);
- if (err2)
- {
- svn_error_clear(err);
- return err2;
- }
-
- SVN_ERR(err);
+ SVN_ERR(svn_error_compose_create(
+ svn_ra_serf__error_on_status(handler->sline, handler->path,
+ handler->location),
+ err));
if (handler->done && apr_hash_count(mergeinfo_ctx->result_catalog))
*catalog = mergeinfo_ctx->result_catalog;
diff --git a/subversion/libsvn_ra_serf/options.c b/subversion/libsvn_ra_serf/options.c
index 0af0b1599c6d..a3c2fb95c881 100644
--- a/subversion/libsvn_ra_serf/options.c
+++ b/subversion/libsvn_ra_serf/options.c
@@ -362,6 +362,8 @@ options_response_handler(serf_request_t *request,
capability_no);
svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS,
capability_no);
+ svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE,
+ capability_no);
/* Then see which ones we can discover. */
serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback,
@@ -436,11 +438,12 @@ svn_ra_serf__v2_get_youngest_revnum(svn_revnum_t *youngest,
SVN_ERR(create_options_req(&opt_ctx, session, conn, scratch_pool));
SVN_ERR(svn_ra_serf__context_run_one(opt_ctx->handler, scratch_pool));
- SVN_ERR(svn_ra_serf__error_on_status(opt_ctx->handler->sline.code,
+ SVN_ERR(svn_ra_serf__error_on_status(opt_ctx->handler->sline,
opt_ctx->handler->path,
opt_ctx->handler->location));
*youngest = opt_ctx->youngest_rev;
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(*youngest));
return SVN_NO_ERROR;
}
@@ -460,7 +463,7 @@ svn_ra_serf__v1_get_activity_collection(const char **activity_url,
SVN_ERR(create_options_req(&opt_ctx, session, conn, scratch_pool));
SVN_ERR(svn_ra_serf__context_run_one(opt_ctx->handler, scratch_pool));
- SVN_ERR(svn_ra_serf__error_on_status(opt_ctx->handler->sline.code,
+ SVN_ERR(svn_ra_serf__error_on_status(opt_ctx->handler->sline,
opt_ctx->handler->path,
opt_ctx->handler->location));
@@ -499,7 +502,7 @@ svn_ra_serf__exchange_capabilities(svn_ra_serf__session_t *serf_sess,
}
SVN_ERR(svn_error_compose_create(
- svn_ra_serf__error_on_status(opt_ctx->handler->sline.code,
+ svn_ra_serf__error_on_status(opt_ctx->handler->sline,
serf_sess->session_url.path,
opt_ctx->handler->location),
err));
@@ -517,6 +520,65 @@ svn_ra_serf__exchange_capabilities(svn_ra_serf__session_t *serf_sess,
}
+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,
diff --git a/subversion/libsvn_ra_serf/property.c b/subversion/libsvn_ra_serf/property.c
index 63972e8597f1..586d38ff46ca 100644
--- a/subversion/libsvn_ra_serf/property.c
+++ b/subversion/libsvn_ra_serf/property.c
@@ -635,7 +635,7 @@ svn_ra_serf__wait_for_props(svn_ra_serf__handler_t *handler,
err = svn_ra_serf__context_run_one(handler, scratch_pool);
- err2 = svn_ra_serf__error_on_status(handler->sline.code,
+ err2 = svn_ra_serf__error_on_status(handler->sline,
handler->path,
handler->location);
diff --git a/subversion/libsvn_ra_serf/ra_serf.h b/subversion/libsvn_ra_serf/ra_serf.h
index 3f3f3ded05af..f6310b351dc7 100644
--- a/subversion/libsvn_ra_serf/ra_serf.h
+++ b/subversion/libsvn_ra_serf/ra_serf.h
@@ -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_info_t **commit_info,
/** 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.
@@ -1744,7 +1759,7 @@ svn_ra_serf__credentials_callback(char **username, char **password,
* where it necessary.
*/
svn_error_t *
-svn_ra_serf__error_on_status(int status_code,
+svn_ra_serf__error_on_status(serf_status_line sline,
const char *path,
const char *location);
diff --git a/subversion/libsvn_ra_serf/replay.c b/subversion/libsvn_ra_serf/replay.c
index 1fcecf43f878..2d385f345f36 100644
--- a/subversion/libsvn_ra_serf/replay.c
+++ b/subversion/libsvn_ra_serf/replay.c
@@ -696,7 +696,7 @@ svn_ra_serf__replay(svn_ra_session_t *ra_session,
err = svn_ra_serf__context_run_wait(&replay_ctx->done, session, pool);
SVN_ERR(svn_error_compose_create(
- svn_ra_serf__error_on_status(handler->sline.code,
+ svn_ra_serf__error_on_status(handler->sline,
handler->path,
handler->location),
err));
@@ -905,7 +905,7 @@ svn_ra_serf__replay_range(svn_ra_session_t *ra_session,
svn_ra_serf__handler_t *done_handler = ctx->report_handler;
done_list = done_list->next;
- SVN_ERR(svn_ra_serf__error_on_status(done_handler->sline.code,
+ SVN_ERR(svn_ra_serf__error_on_status(done_handler->sline,
done_handler->path,
done_handler->location));
svn_pool_destroy(ctx->src_rev_pool);
diff --git a/subversion/libsvn_ra_serf/serf.c b/subversion/libsvn_ra_serf/serf.c
index 601615738043..b0b6346c5a92 100644
--- a/subversion/libsvn_ra_serf/serf.c
+++ b/subversion/libsvn_ra_serf/serf.c
@@ -137,6 +137,10 @@ load_http_auth_types(apr_pool_t *pool, svn_config_t *config,
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 *session,
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 *session,
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 *session,
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 *session,
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));
@@ -392,6 +427,7 @@ svn_ra_serf__open(svn_ra_session_t *session,
svn_ra_serf__session_t *serf_sess;
apr_uri_t url;
const char *client_string = NULL;
+ svn_error_t *err;
if (corrected_url)
*corrected_url = NULL;
@@ -441,6 +477,10 @@ svn_ra_serf__open(svn_ra_session_t *session,
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,
@@ -479,7 +519,23 @@ svn_ra_serf__open(svn_ra_session_t *session,
session->priv = serf_sess;
- return svn_ra_serf__exchange_capabilities(serf_sess, corrected_url, pool);
+ err = svn_ra_serf__exchange_capabilities(serf_sess, corrected_url, pool);
+
+ /* serf should produce a usable error code instead of APR_EGENERAL */
+ 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 (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(). */
diff --git a/subversion/libsvn_ra_serf/update.c b/subversion/libsvn_ra_serf/update.c
index 21ed2dfc9cd9..06a16c06effd 100644
--- a/subversion/libsvn_ra_serf/update.c
+++ b/subversion/libsvn_ra_serf/update.c
@@ -1268,7 +1268,7 @@ handle_stream(serf_request_t *request,
/* ### new field. make sure we didn't miss some initialization. */
SVN_ERR_ASSERT(fetch_ctx->handler != NULL);
- err = svn_ra_serf__error_on_status(fetch_ctx->handler->sline.code,
+ err = svn_ra_serf__error_on_status(fetch_ctx->handler->sline,
fetch_ctx->info->name,
fetch_ctx->handler->location);
if (err)
@@ -2739,7 +2739,7 @@ setup_update_report_headers(serf_bucket_t *headers,
if (report->sess->using_compression)
{
serf_bucket_headers_setn(headers, "Accept-Encoding",
- "gzip;svndiff1;q=0.9,svndiff;q=0.8");
+ "gzip,svndiff1;q=0.9,svndiff;q=0.8");
}
else
{
@@ -2891,7 +2891,7 @@ finish_report(void *report_baton,
{
return svn_error_trace(
svn_error_compose_create(
- svn_ra_serf__error_on_status(handler->sline.code,
+ svn_ra_serf__error_on_status(handler->sline,
handler->path,
handler->location),
err));
diff --git a/subversion/libsvn_ra_serf/util.c b/subversion/libsvn_ra_serf/util.c
index c7a171627e2b..ce1e31a94c8a 100644
--- a/subversion/libsvn_ra_serf/util.c
+++ b/subversion/libsvn_ra_serf/util.c
@@ -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,
@@ -477,7 +475,7 @@ connection_closed(svn_ra_serf__connection_t *conn,
{
if (why)
{
- SVN_ERR_MALFUNCTION();
+ return svn_error_wrap_apr(why, NULL);
}
if (conn->session->using_ssl)
@@ -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)
{
@@ -2390,17 +2385,17 @@ svn_ra_serf__report_resource(const char **report_target,
}
svn_error_t *
-svn_ra_serf__error_on_status(int status_code,
+svn_ra_serf__error_on_status(serf_status_line sline,
const char *path,
const char *location)
{
- switch(status_code)
+ switch(sline.code)
{
case 301:
case 302:
case 307:
return svn_error_createf(SVN_ERR_RA_DAV_RELOCATED, NULL,
- (status_code == 301)
+ (sline.code == 301)
? _("Repository moved permanently to '%s';"
" please relocate")
: _("Repository moved temporarily to '%s';"
@@ -2415,8 +2410,20 @@ svn_ra_serf__error_on_status(int status_code,
case 423:
return svn_error_createf(SVN_ERR_FS_NO_LOCK_TOKEN, NULL,
_("'%s': no lock token available"), path);
+
+ case 411:
+ return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
+ _("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)
+ return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
+ _("Unexpected HTTP status %d '%s' on '%s'\n"),
+ sline.code, sline.reason, path);
+
return SVN_NO_ERROR;
}
diff --git a/subversion/libsvn_ra_serf/xml.c b/subversion/libsvn_ra_serf/xml.c
index 95017d5e3be4..a95eaccd2199 100644
--- a/subversion/libsvn_ra_serf/xml.c
+++ b/subversion/libsvn_ra_serf/xml.c
@@ -615,6 +615,14 @@ svn_ra_serf__xml_cb_start(svn_ra_serf__xml_context_t *xmlctx,
}
if (scan->ns == NULL)
{
+ if (current->state == 0)
+ {
+ return svn_error_createf(
+ SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+ _("XML Parsing failed: Unexpected root element '%s'"),
+ elemname.name);
+ }
+
xmlctx->waiting = elemname;
/* ### return? */
return SVN_NO_ERROR;