commit 02d6ae5a5714ad24ea0d56a1d575c3dc72bb6949
Author:     Laslo Hunhold <[email protected]>
AuthorDate: Tue Feb 27 11:36:24 2018 +0100
Commit:     Laslo Hunhold <[email protected]>
CommitDate: Tue Feb 27 11:36:24 2018 +0100

    Add support for adding a prefix to a target when matching vhosts
    
    This makes quark's vhost-handling very powerful while still being
    simple.
    
    Imagine you have a website with a subdomain you really want
    to move back to your main domain.
    Say the subdomain is called "old.example.org" and you want to serve it
    under "example.org" but in the subdirectory "old/", i.e. you want to
    redirect a request "old.example.org/subdir/" to "example.org/old/subdir".
    
    For a vhost-handler that only takes 4 arguments for each vhost this is
    actually pretty powerful.

diff --git a/config.def.h b/config.def.h
index 5956647..1875ed3 100644
--- a/config.def.h
+++ b/config.def.h
@@ -17,10 +17,12 @@ static struct {
        const char *name;
        const char *regex;
        const char *dir;
+       const char *prefix;
        regex_t re;
 } vhost[] = {
-       /* canonical host      host regex                     directory      */
-       { "example.org",       "^(www\\.)?example\\.org$",    "/example.org" },
+       /* canonical host    host regex                     directory         
prefix */
+       { "example.org",     "^(www\\.)?example\\.org$",    "/example.org",   
NULL   },
+       { "example.org",     "old\\.example\\.org",         "/",              
"/old" },
 };
 
 /* mime-types */
diff --git a/http.c b/http.c
index d17a019..03ba680 100644
--- a/http.c
+++ b/http.c
@@ -320,6 +320,9 @@ http_send_response(int fd, struct request *r)
        char *p, *q, *mime;
        const char *vhostmatch, *err;
 
+       /* make a working copy of the target */
+       memcpy(realtarget, r->target, sizeof(realtarget));
+
        /* match vhost */
        vhostmatch = NULL;
        if (vhosts) {
@@ -338,10 +341,17 @@ http_send_response(int fd, struct request *r)
                if (i == LEN(vhost)) {
                        return http_send_status(fd, S_NOT_FOUND);
                }
+
+               /* if we have a vhost prefix, prepend it to the target */
+               if (vhost[i].prefix) {
+                       if (snprintf(realtarget, sizeof(realtarget), "%s%s",
+                           vhost[i].prefix, realtarget) >= sizeof(realtarget)) 
{
+                               return http_send_status(fd, 
S_REQUEST_TOO_LARGE);
+                       }
+               }
        }
 
        /* normalize target */
-       memcpy(realtarget, r->target, sizeof(realtarget));
        if (normabspath(realtarget)) {
                return http_send_status(fd, S_BAD_REQUEST);
        }
@@ -369,7 +379,7 @@ http_send_response(int fd, struct request *r)
                }
        }
 
-       /* redirect if targets differ or host is non-canonical */
+       /* redirect if targets differ, host is non-canonical or we prefixed */
        if (strcmp(r->target, realtarget) || (vhosts && vhostmatch &&
            strcmp(r->field[REQ_HOST], vhostmatch))) {
                /* do we need to add a port to the Location? */

Reply via email to