Branko Čibej wrote:
It is a confusing error message, though. The redirect "cycle" is only
Subversion that made it a cycle, and is not the real problem. We could
do better.

We could. Not canonicalizing the value of the Location header is an
option; if it's not a valid URL, that's the server admin's problem, not
ours (and as noted a number of times in other conversations, Subversion
is not a browser so we don't have to worry about producing user-friendly
URLs).

The attached patch, 'serf-no-canonicalize-redirect-1.patch', stops canonicalizing the redirect, solving this problem.

I have only tested that it fixes the non-repository case I reported, and verified that the existing test suite still passes. I haven't tested what difference it makes to any currently untested forms of redirect when accessing a repo.

WDYT?

ps. It's my favourite kind of patch: a code reduction/simplification.

- Julian
When following an HTTP redirect, use the Location header URL exactly.

Previously we canonicalized the redirect URL, which could lead to a redirect
loop. Then Subversion would report a redirect loop as the error, potentially
hiding a more interesting error such as when the target is not in fact a
Subversion repository.

A manual test case (on a non-repository):
  before:
    $ svn ls https://archive.apache.org/dist
    Redirecting to URL 'https://archive.apache.org/dist':
    Redirecting to URL 'https://archive.apache.org/dist':
    svn: E195019: Redirect cycle detected for URL 'https://archive.apache.org/dist'

  after:
    $ svn ls https://archive.apache.org/dist
    Redirecting to URL 'https://archive.apache.org/dist/':
    svn: E170013: Unable to connect to a repository at URL 'https://archive.apache.org/dist/'
    svn: E175003: The server at 'https://archive.apache.org/dist/' does not support the HTTP/DAV protocol

* subversion/libsvn_ra_serf/options.c
  (svn_ra_serf__exchange_capabilities): Don't canonicalize the redirect URL.

* subversion/libsvn_ra_serf/util.c
  (response_get_location): Don't canonicalize the redirect URL.
--This line, and those below, will be ignored--

Index: subversion/libsvn_ra_serf/options.c
===================================================================
--- subversion/libsvn_ra_serf/options.c	(revision 1866676)
+++ subversion/libsvn_ra_serf/options.c	(working copy)
@@ -572,29 +572,26 @@ svn_ra_serf__exchange_capabilities(svn_r
           return svn_error_create(
                     SVN_ERR_RA_DAV_RESPONSE_HEADER_BADNESS, NULL,
                     _("Location header not set on redirect response"));
         }
       else if (svn_path_is_url(opt_ctx->handler->location))
         {
-          *corrected_url = svn_uri_canonicalize(opt_ctx->handler->location,
-                                                result_pool);
+          *corrected_url = apr_pstrdup(result_pool, opt_ctx->handler->location);
         }
       else
         {
           /* RFC1945 and RFC2616 state that the Location header's value
              (from whence this CORRECTED_URL comes), if present, must be an
              absolute URI.  But some Apache versions (those older than 2.2.11,
              it seems) transmit only the path portion of the URI.
              See issue #3775 for details. */
 
           apr_uri_t corrected_URI = serf_sess->session_url;
 
           corrected_URI.path = (char *)corrected_url;
-          *corrected_url = svn_uri_canonicalize(
-                              apr_uri_unparse(scratch_pool, &corrected_URI, 0),
-                              result_pool);
+          *corrected_url = apr_uri_unparse(result_pool, &corrected_URI, 0);
         }
 
       return SVN_NO_ERROR;
     }
   else if (opt_ctx->handler->sline.code >= 300
            && opt_ctx->handler->sline.code < 399)
Index: subversion/libsvn_ra_serf/util.c
===================================================================
--- subversion/libsvn_ra_serf/util.c	(revision 1866676)
+++ subversion/libsvn_ra_serf/util.c	(working copy)
@@ -1113,25 +1113,23 @@ response_get_location(serf_bucket_t *res
       status = apr_uri_parse(scratch_pool, base_url, &uri);
 
       if (status != APR_SUCCESS)
         return NULL;
 
       /* Replace the path path with what we got */
-      uri.path = (char*)svn_urlpath__canonicalize(location, scratch_pool);
+      uri.path = apr_pstrdup(scratch_pool, location);
 
       /* And make APR produce a proper full url for us */
-      location = apr_uri_unparse(scratch_pool, &uri, 0);
-
-      /* Fall through to ensure our canonicalization rules */
+      return apr_uri_unparse(result_pool, &uri, 0);
     }
   else if (!svn_path_is_url(location))
     {
       return NULL; /* Any other formats we should support? */
     }
 
-  return svn_uri_canonicalize(location, result_pool);
+  return apr_pstrdup(result_pool, location);
 }
 
 
 /* Implements svn_ra_serf__response_handler_t */
 svn_error_t *
 svn_ra_serf__expect_empty_body(serf_request_t *request,

Reply via email to