apachemod-rewritesubdomainvirtual-hostsmod-dav-svn

Dynamic subversion repos via subdomains (in Apache)


I'm trying to set up a subdomain-to-repository translation in Apache. Example:

foobars.domain.com -> /server/svnrepos/foobars

I've tried to get this done with mod_rewrite:

RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
RewriteCond %{HTTP_HOST} ^(www\.)?([^.]+)\.domain\.com$ [NC]
RewriteRule ^/svn(.*) /svn/%2$1 [PT]

However, this causes problems with basic svn operations; 'checkout' causes this pretty thing:

$ svn co http://foobars.domain.com/svn
svn: '/svn/foobars/!svn/vcc/default' path not found

I don't have any limitations in terms of server setup (my machines, os, etc). Is there any way to get this translation handled by Apache? I've looked at mass virtual hosts, but I don't see a way to extend the concept to DAV locations (I wish there was a VirtualSvnPath...). The way mod_dav_svn forces you to either 1) explicitly define your svn repo path, or 2) define the parent, is very limited.

Perhaps the 'SVNSpecialURI' can be of some use, although I can't find any documentation on it...

Assuming that my ultimate goal is to map a subdomain to an SVNPath, what are my options?

My current conf as a reference:

<VirtualHost *:80 *:443>
    ServerAdmin admin@domain.com
    DocumentRoot "/server/www"
    ServerName domain.com
    ServerAlias *.domain.com www.domain.com domain.com
    ErrorLog logs/domain-error_log
    CustomLog logs/domain-access_log common

    DirectorySlash Off

    RewriteLogLevel 9
    RewriteLog /server/log/apache-rewrite.log

    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
    RewriteCond %{HTTP_HOST} ^(www\.)?([^.]+)\.domain\.com$ [NC]
    RewriteRule ^/svn$ /svn/ [QSA]

    RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
    RewriteCond %{HTTP_HOST} ^(www\.)?([^.]+)\.domain\.com$ [NC]
    RewriteRule ^/svn(.*) /svn/%2$1 [PT]

<Location /svn>
    DAV svn
    SVNParentPath /server/svn
</Location>


Solution

  • In the interest of Open Source (yay!), I'll post my solution. I found no built-in solution to my problem, so I spent a few hours on the mod_dav_svn.so sources and came up with this patch:

    Index: subversion/mod_dav_svn/mod_dav_svn.c
    ===================================================================
    --- subversion/mod_dav_svn/mod_dav_svn.c        (revision 1049733)
    +++ subversion/mod_dav_svn/mod_dav_svn.c        (working copy)
    @@ -426,9 +426,14 @@
    dav_svn__get_fs_parent_path(request_rec *r)
     {
       dir_conf_t *conf;
    +  char *tokens, *subdomain, *last_str;
    
       conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
    -  return conf->fs_parent_path;
    +
    +  tokens = apr_pstrdup(r->pool, r->hostname);   // copy hostname
    +  subdomain = apr_strtok(tokens, ".", &last_str);
    +
    +  return (const char *) apr_pstrcat(r->pool, conf->fs_parent_path, "/", subdomain, NULL);
     }
    

    Essentially, this grabs the current hostname (from the pending request 'request_rec'), slices away the first token (subdomain), and concatenates that with the proper SVNParentPath (conf->fs_parent_path) and voila! Everything works as it should. Here's my server config (notice how simple it is now):

    <VirtualHost *:80 *:443>
        ServerAdmin admin@domain.com
        DocumentRoot "/server/www"
        ServerName domain.com
        ServerAlias *.domain.com www.domain.com domain.com
        ErrorLog logs/domain-error_log
        CustomLog logs/domain-access_log common
    
        <Location /svn>
            DAV svn
            SVNParentPath /server/svn
            SVNListParentPath on
        </Location>
    </VirtualHost>
    

    Notes:

    I hope that I used the apr_* functions correctly, if there are any caveats, I'd like some feedback :)

    Tested on Centos with latest mod_dav_svn tree.