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.
This commit is contained in:
parent
34189e0a1f
commit
9ff3f780e1
1 changed files with 48 additions and 28 deletions
76
http.c
76
http.c
|
@ -358,7 +358,7 @@ http_send_response(int fd, struct request *r)
|
||||||
int hasport, ipv6host;
|
int hasport, ipv6host;
|
||||||
static char realtarget[PATH_MAX], tmptarget[PATH_MAX], t[TIMESTAMP_LEN];
|
static char realtarget[PATH_MAX], tmptarget[PATH_MAX], t[TIMESTAMP_LEN];
|
||||||
char *p, *q, *mime;
|
char *p, *q, *mime;
|
||||||
const char *vhostmatch, *err;
|
const char *vhostmatch, *targethost, *err;
|
||||||
|
|
||||||
/* make a working copy of the target */
|
/* make a working copy of the target */
|
||||||
memcpy(realtarget, r->target, sizeof(realtarget));
|
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 */
|
/* redirect if targets differ, host is non-canonical or we prefixed */
|
||||||
if (strcmp(r->target, realtarget) || (s.vhost && vhostmatch &&
|
if (strcmp(r->target, realtarget) || (s.vhost && vhostmatch &&
|
||||||
strcmp(r->field[REQ_HOST], 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 */
|
||||||
encode(realtarget, tmptarget);
|
encode(realtarget, tmptarget);
|
||||||
|
|
||||||
/* send redirection header */
|
/* send redirection header */
|
||||||
if (dprintf(fd,
|
if (s.vhost) {
|
||||||
"HTTP/1.1 %d %s\r\n"
|
/* absolute redirection URL */
|
||||||
"Date: %s\r\n"
|
targethost = r->field[REQ_HOST][0] ? vhostmatch ?
|
||||||
"Connection: close\r\n"
|
vhostmatch : r->field[REQ_HOST] : s.host ?
|
||||||
"Location: //%s%s%s%s%s%s\r\n"
|
s.host : "localhost";
|
||||||
"\r\n",
|
|
||||||
S_MOVED_PERMANENTLY,
|
/* do we need to add a port to the Location? */
|
||||||
status_str[S_MOVED_PERMANENTLY],
|
hasport = s.port && strcmp(s.port, "80");
|
||||||
timestamp(time(NULL), t), ipv6host ? "[" : "",
|
|
||||||
r->field[REQ_HOST][0] ? (s.vhost && vhostmatch) ?
|
/* RFC 2732 specifies to use brackets for IPv6-addresses
|
||||||
vhostmatch : r->field[REQ_HOST] : s.host ?
|
* in URLs, so we need to check if our host is one and
|
||||||
s.host : "localhost",
|
* honor that later when we fill the "Location"-field */
|
||||||
ipv6host ? "]" : "", hasport ? ":" : "",
|
if ((ipv6host = inet_pton(AF_INET6, targethost,
|
||||||
hasport ? s.port : "", tmptarget) < 0) {
|
&res)) < 0) {
|
||||||
return S_REQUEST_TIMEOUT;
|
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;
|
return S_MOVED_PERMANENTLY;
|
||||||
|
|
Loading…
Reference in a new issue