quark

quark web server
git clone git://git.suckless.org/quark
Log | Files | Refs | LICENSE

commit 9ff3f780e1d1912b89727140df7c1529ab8c5146
parent 34189e0a1f288e05ce528bcab28b922d53d5e471
Author: Laslo Hunhold <dev@frign.de>
Date:   Mon,  2 Jul 2018 18:43:06 +0200

Send a relative redirection header wherever possible

This makes quark much more flexible when it is run behind a network
filter or other kind of tunnel. Only send an absolute redirection when
we are handling vhosts.

Diffstat:
Mhttp.c | 76++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
1 file changed, 48 insertions(+), 28 deletions(-)

diff --git a/http.c b/http.c @@ -358,7 +358,7 @@ http_send_response(int fd, struct request *r) int hasport, ipv6host; static char realtarget[PATH_MAX], tmptarget[PATH_MAX], t[TIMESTAMP_LEN]; char *p, *q, *mime; - const char *vhostmatch, *err; + const char *vhostmatch, *targethost, *err; /* make a working copy of the target */ memcpy(realtarget, r->target, sizeof(realtarget)); @@ -442,37 +442,57 @@ http_send_response(int fd, struct request *r) /* redirect if targets differ, host is non-canonical or we prefixed */ if (strcmp(r->target, realtarget) || (s.vhost && vhostmatch && strcmp(r->field[REQ_HOST], vhostmatch))) { - /* do we need to add a port to the Location? */ - hasport = s.port && strcmp(s.port, "80"); - - /* RFC 2732 specifies to use brackets for IPv6-addresses in - * URLs, so we need to check if our host is one and honor that - * later when we fill the "Location"-field */ - if ((ipv6host = inet_pton(AF_INET6, r->field[REQ_HOST][0] ? - r->field[REQ_HOST] : s.host ? s.host : - "localhost", &res)) < 0) { - return http_send_status(fd, S_INTERNAL_SERVER_ERROR); - } - /* encode realtarget */ encode(realtarget, tmptarget); /* send redirection header */ - if (dprintf(fd, - "HTTP/1.1 %d %s\r\n" - "Date: %s\r\n" - "Connection: close\r\n" - "Location: //%s%s%s%s%s%s\r\n" - "\r\n", - S_MOVED_PERMANENTLY, - status_str[S_MOVED_PERMANENTLY], - timestamp(time(NULL), t), ipv6host ? "[" : "", - r->field[REQ_HOST][0] ? (s.vhost && vhostmatch) ? - vhostmatch : r->field[REQ_HOST] : s.host ? - s.host : "localhost", - ipv6host ? "]" : "", hasport ? ":" : "", - hasport ? s.port : "", tmptarget) < 0) { - return S_REQUEST_TIMEOUT; + if (s.vhost) { + /* absolute redirection URL */ + targethost = r->field[REQ_HOST][0] ? vhostmatch ? + vhostmatch : r->field[REQ_HOST] : s.host ? + s.host : "localhost"; + + /* do we need to add a port to the Location? */ + hasport = s.port && strcmp(s.port, "80"); + + /* RFC 2732 specifies to use brackets for IPv6-addresses + * in URLs, so we need to check if our host is one and + * honor that later when we fill the "Location"-field */ + if ((ipv6host = inet_pton(AF_INET6, targethost, + &res)) < 0) { + return http_send_status(fd, + S_INTERNAL_SERVER_ERROR); + } + + if (dprintf(fd, + "HTTP/1.1 %d %s\r\n" + "Date: %s\r\n" + "Connection: close\r\n" + "Location: //%s%s%s%s%s%s\r\n" + "\r\n", + S_MOVED_PERMANENTLY, + status_str[S_MOVED_PERMANENTLY], + timestamp(time(NULL), t), + ipv6host ? "[" : "", + targethost, + ipv6host ? "]" : "", hasport ? ":" : "", + hasport ? s.port : "", tmptarget) < 0) { + return S_REQUEST_TIMEOUT; + } + } else { + /* relative redirection URL */ + if (dprintf(fd, + "HTTP/1.1 %d %s\r\n" + "Date: %s\r\n" + "Connection: close\r\n" + "Location: %s\r\n" + "\r\n", + S_MOVED_PERMANENTLY, + status_str[S_MOVED_PERMANENTLY], + timestamp(time(NULL), t), + tmptarget) < 0) { + return S_REQUEST_TIMEOUT; + } } return S_MOVED_PERMANENTLY;