This patch hasn't left my sphere of interest since it first arrived. It
*has*, however, stirred some quite humorous (and hallucination-filled)
interactions with Gemini, plus some frustratingly unproductive spelunking
through our mailing list archives on multiple occasions.  The question I
was trying to answer was:  Why didn't I/we make this (rather simple and
obvious) change when developing the WebDAV proxy feature in the first place?

This morning -- halfway through writing this email -- I decided to try a
complete read of the mirror.c code to see if triggered anything.  And by
golly, I think I found it.

In svn_dav__location_in_filter(), I found this comment:

    /* ### FIXME: While we want to fix up any locations in proxied XML
       ### requests, we do *not* want to be futzing with versioned (or
       ### to-be-versioned) data, such as the file contents present in
       ### PUT requests and properties in PROPPATCH requests.
       ### See issue #3445 for details. */

At the time, "issue #3445" referred to the old Tigris issue tracker, but
thankfully our move to JIRA was so incredibly well-planned that the
analogous issue there was easy enough to find.  And at
https://issues.apache.org/jira/browse/SVN-3445, you can read the history of
the problem.  TL;DR:  If the master and slave paths differ, actual
versioned file content can be munged.

I don't have the setup to verify this situation today, but I suspect that
Jordan does.  What happens when you repository URIs differ and a, say, a
text file that contains the URL of the master repository is committed?
Does that file's content on the slave mirror repository still carry the URL
of the master repository, or has it been tweaked to look like a mixture of
master hostname and slave path?

-- Mike

On Wed, Jan 14, 2026 at 3:20 PM C. Michael Pilato <[email protected]>
wrote:

> I'm too long out of the game to offer meaningful review and testing on
> this, but I definitely appreciate the thorough write-up.  And given the
> comments I left sprinkled in that source file (so many years ago...) about
> how inefficient some of the filtering was when the master/slave repository
> paths were identical, chances are pretty good that I did most of my testing
> in exactly that configuration.
>
> -- Mike
>
> On Wed, Jan 14, 2026 at 7:18 AM Jordan Peck via dev <
> [email protected]> wrote:
>
>> Hi,
>>
>> I've identified and fixed a bug in mod_dav_svn's master/slave proxy
>> functionality (SVNMasterURI) that causes COPY and MOVE operations to
>> fail with a 400 error when the slave and master repositories are
>> hosted at different paths.
>>
>>
>> STEPS TO REPRODUCE
>> ==================
>>
>> 1. Configure a master SVN server with the repository at /repo:
>>
>>    # Master server (master-server.example.com)
>>    <Location /repo>
>>        DAV svn
>>        SVNPath /var/svn/myrepo
>>    </Location>
>>
>> 2. Configure a slave SVN server with the repository at a different
>>    path (/svn/repo) and SVNMasterURI pointing to the master:
>>
>>    # Slave server (slave-server.example.com)
>>    <Location /svn/repo>
>>        DAV svn
>>        SVNPath /var/svn/myrepo-slave
>>        SVNMasterURI http://master-server.example.com/repo
>>    </Location>
>>
>> 3. Ensure the slave repository is a synced mirror of the master
>>    (via svnsync).
>>
>> 4. Attempt a COPY operation through the slave to create a branch:
>>
>>    svn copy http://slave-server.example.com/svn/repo/trunk \
>>             http://slave-server.example.com/svn/repo/branches/new-feature
>> \
>>             -m "Creating new feature branch"
>>
>>
>> EXPECTED RESULT
>> ===============
>>
>> The COPY request is proxied to the master and the branch is created
>> successfully.
>>
>>
>> ACTUAL RESULT
>> =============
>>
>> The operation fails with HTTP 400 Bad Request. Server logs show the
>> master receiving a Destination header with path
>> /svn/repo/branches/new-feature which does not exist on the master
>> (the correct path would be /repo/branches/new-feature).
>>
>>
>> ROOT CAUSE
>> ==========
>>
>> In subversion/mod_dav_svn/mirror.c, the proxy_request_fixup() function
>> correctly rewrites the Request-URI when proxying requests to the master.
>> However, WebDAV COPY and MOVE operations specify their destination in
>> the Destination HTTP header, which is not rewritten.
>>
>> The existing filters handle:
>> - Request body rewriting (dav_svn__location_in_filter)
>> - Response body rewriting (dav_svn__location_body_filter)
>> - Response Location header rewriting (dav_svn__location_header_filter)
>>
>> But there is no rewriting for the incoming Destination request header.
>>
>> When paths are identical on slave and master, this bug is masked
>> because the path portion extracted from the Destination header happens
>> to be valid on both servers. The bug only manifests when the repository
>> paths differ.
>>
>>
>> FIX
>> ===
>>
>> The attached patch adds rewriting of the Destination header in
>> proxy_request_fixup(). It parses the header, replaces the slave's root
>> path with the master's path, and updates the header before the request
>> is proxied.
>>
>> I have tested this fix and can confirm it fixes the issue in my testing.
>>
>> Please review the attached patch.
>>
>> Thanks,
>> Jordan Peck
>>
>

Reply via email to