How can I configure Apache to redirect a subdirectory to a subversion repo?

457

Short answer: Use the PT flag on your RewriteRule.

First, a little Apache backstory. When Apache receives a request, it goes though a process of mapping that request to the local storage. After that, Apache actually has two pieces of data on what you requested. The request url, and the file path. So a request for /svn/blah is translated into /var/www/vhosts/myserver.com/html/svn/blah and that path is stored separately. mod_rewrite lets you tweak this behavior to route urls where you want.

Now, the two RewriteRules you have there are implicitly doing different things.

  • The first one you have there is a rewrite. It takes a url like /svn/blah and instead of using the behavior above, it maps it as if you actually requested /svn/myrepo/blah, so the resulting filepath would be /var/www/vhosts/myserver.com/html/svn/myrepo/blah. However, and here's the sticking point, it does not modify the requested url. The request url is still /svn/blah, apache just now thinks that file is to be found at .../svn/myrepo/blah rather than .../svn/blah.

    Why does this matter you ask? Because the subversion module doesn't use the filepath. It looks at the request url. So apache and mod_rewrite just wasted time doing all that, because mod_dav_svn just ignores it. What you need is for mod_rewrite to change the request url. And that's what PT does. It modifies both the request url and the file path, so later when it gets to mod_dav_svn, it will see the changed url.

  • The second one is a redirect. Since the substitution starts with http:// and apache doesn't have a virtualhost named 192.168.0.1, it assumes you actually meant to put an R in your flags, since it can't translate that into a filepath. That is sending back a "Hey, it's over here" message to the subversion client, and it's making another request for it.

Now, having said all that, you're never going to have more than one repository on there anyway with this setup unless you do something to force mod_rewrite to skip the urls of the other repositories. mod_rewrite will cheerfully change /svn/bignewproject/blah into /svn/myrepo/bignewproject/blah for you every time. You could add a rule before the RewriteRule you have such as:

RewriteRule ^/svn/(myrepo|myotherrepo|coolproject|stuff|etc)/ - [S=1]

That will cause it to skip the next rule. However, you're going to be updating it by hand from here on out. You might be able to pull off something automated with some RewriteCond magic, but it'll probably be tricky. I'm not really familiar with that, so someone else would have to help you out there.

If this is only used by a small group of people, then you might be better off skipping this rewriting stuff entirely and just update everyone's working copies. svn switch --relocate is meant specifically for situations where the repos is moved and you just want to update your working copy without checking it out again. I understand there are situations where this simply isn't feasible though.

Share:
457

Related videos on Youtube

Simon Söderman
Author by

Simon Söderman

Updated on September 17, 2022

Comments

  • Simon Söderman
    Simon Söderman over 1 year

    Scenario: Validate that my class issues a RestRequest with the provided IRestclient where certain Parameters are set on the request.

        public class MyClass {
        private readonly IRestClient _client;
    
        public MyClass(IRestClient client) {
            _client = client;
        }
    
        void DoIt() {
            var req = new RestRequest { Method = WebMethod.Get, Path = "/DoIt" };
            req.AddParameter("key1", "value1");
            req.AddParameter("key2", "value2");
    
            var resp = _client.Request(req);
        }
    
    }
    
    [TestFixture]
    public class MyClassTests {
        [Test]
        public void VerifyDoIt() {
            var client = MockRepository.GenerateStrictMock<IRestClient>();
            var resp = new RestResponse { StatusCode = HttpStatusCode.OK };
            client.Expect(x => x.Request(null)).IgnoreArguments().WhenCalled(inv => {
                var req = inv.Arguments[0] as RestRequest;
                //NO WAY TO VALIDATE THAT PARAMETERS HAS BEEN SET!
                inv.ReturnValue = resp;
            });
        }
    }
    

    Is Hammock simply not testable in this fashion or am I missing something crucial?

    Edit: this is not a question about on how to access/validate method parameters with Rhino.Mocks, but rather how/if Hammock supports testing/validating that request parameters are set in unit-test scenarios.

    • Swoogan
      Swoogan over 14 years
      "but when I try to get it to redirect using the domain name itself, it seems to cause problems" Can you clarify what the problem is?
    • PatrickSteele
      PatrickSteele over 12 years
      So do you want to check the values of the "req" variable created inside the DoIt() method?
    • Simon Söderman
      Simon Söderman over 12 years
      sorry, I realize now that my question is a bit unclear to what solution I want. this is more of a Hammock question than a Rhino.Mocks question. eg. does hammock not support this, or is there some hidden feature in Hammock that lets one access and validate these things.
  • Rahim
    Rahim over 14 years
    That would work if he were still running a second server. It looks like he wants to move the repository to the new server and just not change the URL.
  • Philip Reynolds
    Philip Reynolds over 14 years
    You can proxy to the local machine.