Browse Source

[core] redirect to dir using relative-path

Location response header is permitted to use relative-path in
RFC 7231 Section 7.1.2. Location

Prefer relative path in redirection for the benefit of reverse proxies
and CDNs.  Doing so also avoids potentially disclosing internal schemes
and server names which client might not be able to directly reach.

To restore prior behavior of sending a fully-qualified absolute URI:
server.feature-flags += ("absolute-dir-redirect" => "enable")

x-ref:
  https://bz.apache.org/bugzilla/show_bug.cgi?id=63357
master
Glenn Strauss 1 year ago
parent
commit
8e2cf55250
  1. 1
      src/base.h
  2. 4
      src/configfile.c
  3. 13
      src/http-header-glue.c
  4. 8
      tests/core-response.t

1
src/base.h

@ -94,6 +94,7 @@ typedef struct {
unsigned char high_precision_timestamps;
unsigned char h2proto;
unsigned short http_url_normalize;
unsigned char absolute_dir_redirect;
unsigned short max_worker;
unsigned short max_fds;

4
src/configfile.c

@ -793,6 +793,10 @@ static int config_insert_srvconf(server *srv) {
config_plugin_value_tobool(
array_get_element_klen(cpv->v.a,
CONST_STR_LEN("server.h2c")), 0);
srv->srvconf.absolute_dir_redirect =
config_plugin_value_tobool(
array_get_element_klen(cpv->v.a,
CONST_STR_LEN("server.absolute-dir-redirect")), 0);
break;
default:/* should not happen */
break;

13
src/http-header-glue.c

@ -30,6 +30,7 @@
#define MAX_HTTP_RESPONSE_FIELD_SIZE 65535
__attribute_cold__
static int http_response_buffer_append_authority(request_st * const r, buffer * const o) {
if (!buffer_string_is_empty(&r->uri.authority)) {
buffer_append_string_buffer(o, &r->uri.authority);
@ -99,10 +100,14 @@ static int http_response_buffer_append_authority(request_st * const r, buffer *
int http_response_redirect_to_directory(request_st * const r, int status) {
buffer *o = r->tmp_buf;
buffer_copy_buffer(o, &r->uri.scheme);
buffer_append_string_len(o, CONST_STR_LEN("://"));
if (0 != http_response_buffer_append_authority(r, o)) {
return -1;
buffer_clear(o);
/* XXX: store flag in global at startup? */
if (r->con->srv->srvconf.absolute_dir_redirect) {
buffer_copy_buffer(o, &r->uri.scheme);
buffer_append_string_len(o, CONST_STR_LEN("://"));
if (0 != http_response_buffer_append_authority(r, o)) {
return -1;
}
}
buffer_append_string_encoded(o, CONST_BUF_LEN(&r->uri.path), ENCODING_REL_URI);
buffer_append_string_len(o, CONST_STR_LEN("/"));

8
tests/core-response.t

@ -76,28 +76,28 @@ $t->{REQUEST} = ( <<EOF
GET /dummydir HTTP/1.0
EOF
);
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://'.$tf->{HOSTNAME}.':'.$tf->{PORT}.'/dummydir/' } ];
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => '/dummydir/' } ];
ok($tf->handle_http($t) == 0, 'internal redirect in directory');
$t->{REQUEST} = ( <<EOF
GET /dummydir?foo HTTP/1.0
EOF
);
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://'.$tf->{HOSTNAME}.':'.$tf->{PORT}.'/dummydir/?foo' } ];
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => '/dummydir/?foo' } ];
ok($tf->handle_http($t) == 0, 'internal redirect in directory + querystring');
$t->{REQUEST} = ( <<EOF
GET /~test%20ä_ HTTP/1.0
EOF
);
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://'.$tf->{HOSTNAME}.':'.$tf->{PORT}.'/~test%20%C3%A4_/' } ];
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => '/~test%20%C3%A4_/' } ];
ok($tf->handle_http($t) == 0, 'internal redirect in directory with special characters');
$t->{REQUEST} = ( <<EOF
GET /~test%20ä_?foo HTTP/1.0
EOF
);
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://'.$tf->{HOSTNAME}.':'.$tf->{PORT}.'/~test%20%C3%A4_/?foo' } ];
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => '/~test%20%C3%A4_/?foo' } ];
ok($tf->handle_http($t) == 0, 'internal redirect in directory with special characters + querystring');
## simple-vhost

Loading…
Cancel
Save