Add support for adding a prefix to a target when matching vhosts - quark - quark web server
 (HTM) git clone git://git.suckless.org/quark
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit 02d6ae5a5714ad24ea0d56a1d575c3dc72bb6949
 (DIR) parent 4948053bee6d4883d988d104316d11ad9a0ca092
 (HTM) Author: Laslo Hunhold <dev@frign.de>
       Date:   Tue, 27 Feb 2018 11:36:24 +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.
       
       Diffstat:
         M config.def.h                        |       6 ++++--
         M http.c                              |      14 ++++++++++++--
       
       2 files changed, 16 insertions(+), 4 deletions(-)
       ---
 (DIR) diff --git 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 */
 (DIR) diff --git 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? */