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.
This commit is contained in:
Laslo Hunhold 2018-02-27 11:36:24 +01:00
parent 4948053bee
commit 02d6ae5a57
2 changed files with 16 additions and 4 deletions

View file

@ -17,10 +17,12 @@ static struct {
const char *name; const char *name;
const char *regex; const char *regex;
const char *dir; const char *dir;
const char *prefix;
regex_t re; regex_t re;
} vhost[] = { } vhost[] = {
/* canonical host host regex directory */ /* canonical host host regex directory prefix */
{ "example.org", "^(www\\.)?example\\.org$", "/example.org" }, { "example.org", "^(www\\.)?example\\.org$", "/example.org", NULL },
{ "example.org", "old\\.example\\.org", "/", "/old" },
}; };
/* mime-types */ /* mime-types */

14
http.c
View file

@ -320,6 +320,9 @@ http_send_response(int fd, struct request *r)
char *p, *q, *mime; char *p, *q, *mime;
const char *vhostmatch, *err; const char *vhostmatch, *err;
/* make a working copy of the target */
memcpy(realtarget, r->target, sizeof(realtarget));
/* match vhost */ /* match vhost */
vhostmatch = NULL; vhostmatch = NULL;
if (vhosts) { if (vhosts) {
@ -338,10 +341,17 @@ http_send_response(int fd, struct request *r)
if (i == LEN(vhost)) { if (i == LEN(vhost)) {
return http_send_status(fd, S_NOT_FOUND); 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 */ /* normalize target */
memcpy(realtarget, r->target, sizeof(realtarget));
if (normabspath(realtarget)) { if (normabspath(realtarget)) {
return http_send_status(fd, S_BAD_REQUEST); 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 && if (strcmp(r->target, realtarget) || (vhosts && vhostmatch &&
strcmp(r->field[REQ_HOST], vhostmatch))) { strcmp(r->field[REQ_HOST], vhostmatch))) {
/* do we need to add a port to the Location? */ /* do we need to add a port to the Location? */