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
move-copy-proxy.patch
Description: Binary data

