summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2016-12-22 12:32:22 -0500
committerGlenn Strauss <gstrauss@gluelogic.com>2017-01-31 14:36:15 -0500
commit4d92366ab21d4b4ae6f4781b9121d6683e0bc909 (patch)
treeadfff59fe275138e0ab0744d46a208ca25a5f772
parentd171be31ae420b415aec1f2e6e33ec4a7570b178 (diff)
downloadlighttpd1.4-4d92366ab21d4b4ae6f4781b9121d6683e0bc909.tar.gz
lighttpd1.4-4d92366ab21d4b4ae6f4781b9121d6683e0bc909.zip
[mod_setenv] directives to overwrite/remove hdrs (fixes #650, fixes #2295)
directives to set value, rather than append values to headers, env setenv.set-request-header setenv.set-response-header setenv.set-environment These directives take precedence over the setenv.add-* counterparts Set a blank value for request or response header to remove the header (blank value in environment will be set as the value; not removed) setenv.*-environment is now deferred to handle_request_env hook. setenv.*-response-header is now processed in handle_response_start hook. x-ref: "setenv.add-or-replace-response-header" https://redmine.lighttpd.net/issues/650 "set-request-header or remove-request-header support for mod_setenv" https://redmine.lighttpd.net/issues/2295
-rw-r--r--src/mod_setenv.c79
-rw-r--r--tests/lighttpd.conf9
-rwxr-xr-xtests/mod-setenv.t26
3 files changed, 103 insertions, 11 deletions
diff --git a/src/mod_setenv.c b/src/mod_setenv.c
index 81c45e3d..52ea5317 100644
--- a/src/mod_setenv.c
+++ b/src/mod_setenv.c
@@ -14,14 +14,12 @@
/* plugin config for all request/connections */
typedef struct {
- int handled; /* make sure that we only apply the headers once */
-} handler_ctx;
-
-typedef struct {
array *request_header;
+ array *set_request_header;
array *response_header;
-
+ array *set_response_header;
array *environment;
+ array *set_environment;
} plugin_config;
typedef struct {
@@ -32,6 +30,11 @@ typedef struct {
plugin_config conf;
} plugin_data;
+typedef struct {
+ int handled; /* make sure that we only apply the headers once */
+ plugin_config conf;
+} handler_ctx;
+
static handler_ctx * handler_ctx_init(void) {
handler_ctx * hctx;
@@ -74,6 +77,9 @@ FREE_FUNC(mod_setenv_free) {
array_free(s->request_header);
array_free(s->response_header);
array_free(s->environment);
+ array_free(s->set_request_header);
+ array_free(s->set_response_header);
+ array_free(s->set_environment);
free(s);
}
@@ -95,6 +101,9 @@ SETDEFAULTS_FUNC(mod_setenv_set_defaults) {
{ "setenv.add-request-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
{ "setenv.add-response-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
{ "setenv.add-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+ { "setenv.set-request-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
+ { "setenv.set-response-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
+ { "setenv.set-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
};
@@ -110,10 +119,16 @@ SETDEFAULTS_FUNC(mod_setenv_set_defaults) {
s->request_header = array_init();
s->response_header = array_init();
s->environment = array_init();
+ s->set_request_header = array_init();
+ s->set_response_header = array_init();
+ s->set_environment = array_init();
cv[0].destination = s->request_header;
cv[1].destination = s->response_header;
cv[2].destination = s->environment;
+ cv[3].destination = s->set_request_header;
+ cv[4].destination = s->set_response_header;
+ cv[5].destination = s->set_environment;
p->config_storage[i] = s;
@@ -132,8 +147,11 @@ static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data
plugin_config *s = p->config_storage[0];
PATCH(request_header);
+ PATCH(set_request_header);
PATCH(response_header);
+ PATCH(set_response_header);
PATCH(environment);
+ PATCH(set_environment);
/* skip the first, the global context */
for (i = 1; i < srv->config_context->used; i++) {
@@ -149,10 +167,16 @@ static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data
if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-request-header"))) {
PATCH(request_header);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.set-request-header"))) {
+ PATCH(set_request_header);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) {
PATCH(response_header);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.set-response-header"))) {
+ PATCH(set_response_header);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-environment"))) {
PATCH(environment);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.set-environment"))) {
+ PATCH(set_environment);
}
}
}
@@ -181,6 +205,7 @@ URIHANDLER_FUNC(mod_setenv_uri_handler) {
hctx->handled = 1;
mod_setenv_patch_connection(srv, con, p);
+ memcpy(&hctx->conf, &p->conf, sizeof(plugin_config));
for (k = 0; k < p->conf.request_header->used; k++) {
data_string *ds = (data_string *)p->conf.request_header->data[k];
@@ -196,8 +221,24 @@ URIHANDLER_FUNC(mod_setenv_uri_handler) {
array_insert_unique(con->request.headers, (data_unset *)ds_dst);
}
- for (k = 0; k < p->conf.environment->used; k++) {
- data_string *ds = (data_string *)p->conf.environment->data[k];
+ for (k = 0; k < hctx->conf.set_request_header->used; ++k) {
+ data_string *ds = (data_string *)hctx->conf.set_request_header->data[k];
+ array_set_key_value(con->request.headers, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
+ }
+
+ return HANDLER_GO_ON;
+}
+
+CONNECTION_FUNC(mod_setenv_handle_request_env) {
+ plugin_data *p = p_d;
+ handler_ctx *hctx = con->plugin_ctx[p->id];
+ if (NULL == hctx) return HANDLER_GO_ON;
+ if (hctx->handled > 1) return HANDLER_GO_ON;
+ hctx->handled = 2;
+ UNUSED(srv);
+
+ for (size_t k = 0; k < hctx->conf.environment->used; ++k) {
+ data_string *ds = (data_string *)hctx->conf.environment->data[k];
data_string *ds_dst;
if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
@@ -210,13 +251,29 @@ URIHANDLER_FUNC(mod_setenv_uri_handler) {
array_insert_unique(con->environment, (data_unset *)ds_dst);
}
- for (k = 0; k < p->conf.response_header->used; k++) {
- data_string *ds = (data_string *)p->conf.response_header->data[k];
+ for (size_t k = 0; k < hctx->conf.set_environment->used; ++k) {
+ data_string *ds = (data_string *)hctx->conf.set_environment->data[k];
+ array_set_key_value(con->environment, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
+ }
+ return HANDLER_GO_ON;
+}
+
+CONNECTION_FUNC(mod_setenv_handle_response_start) {
+ plugin_data *p = p_d;
+ handler_ctx *hctx = con->plugin_ctx[p->id];
+ if (NULL == hctx) return HANDLER_GO_ON;
+
+ for (size_t k = 0; k < hctx->conf.response_header->used; ++k) {
+ data_string *ds = (data_string *)hctx->conf.response_header->data[k];
response_header_insert(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
}
- /* not found */
+ for (size_t k = 0; k < hctx->conf.set_response_header->used; ++k) {
+ data_string *ds = (data_string *)hctx->conf.set_response_header->data[k];
+ response_header_overwrite(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
+ }
+
return HANDLER_GO_ON;
}
@@ -242,6 +299,8 @@ int mod_setenv_plugin_init(plugin *p) {
p->init = mod_setenv_init;
p->handle_uri_clean = mod_setenv_uri_handler;
+ p->handle_request_env = mod_setenv_handle_request_env;
+ p->handle_response_start = mod_setenv_handle_response_start;
p->set_defaults = mod_setenv_set_defaults;
p->cleanup = mod_setenv_free;
diff --git a/tests/lighttpd.conf b/tests/lighttpd.conf
index ed4ff370..3fd8b0da 100644
--- a/tests/lighttpd.conf
+++ b/tests/lighttpd.conf
@@ -83,12 +83,21 @@ setenv.add-environment = (
"TRAC_ENV" => "tracenv",
"SETENV" => "setenv",
)
+setenv.set-environment = (
+ "NEWENV" => "newenv",
+)
setenv.add-request-header = (
"FOO" => "foo",
)
+setenv.set-request-header = (
+ "FOO2" => "foo2",
+)
setenv.add-response-header = (
"BAR" => "foo",
)
+setenv.set-response-header = (
+ "BAR2" => "bar2",
+)
$HTTP["url"] =~ "\.pdf$" {
server.range-requests = "disable"
diff --git a/tests/mod-setenv.t b/tests/mod-setenv.t
index 1e563018..0c3ce764 100755
--- a/tests/mod-setenv.t
+++ b/tests/mod-setenv.t
@@ -8,7 +8,7 @@ BEGIN {
use strict;
use IO::Socket;
-use Test::More tests => 6;
+use Test::More tests => 9;
use LightyTest;
my $tf = LightyTest->new();
@@ -33,6 +33,14 @@ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP
ok($tf->handle_http($t) == 0, 'query second setenv');
$t->{REQUEST} = ( <<EOF
+GET /get-header.pl?NEWENV HTTP/1.0
+Host: www.example.org
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'newenv' } ];
+ok($tf->handle_http($t) == 0, 'query set-environment');
+
+$t->{REQUEST} = ( <<EOF
GET /get-header.pl?HTTP_FOO HTTP/1.0
Host: www.example.org
EOF
@@ -40,6 +48,14 @@ EOF
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'foo' } ];
ok($tf->handle_http($t) == 0, 'query add-request-header');
+$t->{REQUEST} = ( <<EOF
+GET /get-header.pl?HTTP_FOO2 HTTP/1.0
+Host: www.example.org
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'foo2' } ];
+ok($tf->handle_http($t) == 0, 'query set-request-header');
+
$t->{REQUEST} = ( <<EOF
GET /index.html HTTP/1.0
Host: www.example.org
@@ -48,5 +64,13 @@ EOF
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'BAR' => 'foo' } ];
ok($tf->handle_http($t) == 0, 'query add-response-header');
+$t->{REQUEST} = ( <<EOF
+GET /index.html HTTP/1.0
+Host: www.example.org
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'BAR2' => 'bar2' } ];
+ok($tf->handle_http($t) == 0, 'query set-response-header');
+
ok($tf->stop_proc == 0, "Stopping lighttpd");