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:
| M | http.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;