summaryrefslogtreecommitdiffstats
path: root/modules/metadata
diff options
context:
space:
mode:
Diffstat (limited to 'modules/metadata')
-rw-r--r--modules/metadata/mod_headers.c148
1 files changed, 114 insertions, 34 deletions
diff --git a/modules/metadata/mod_headers.c b/modules/metadata/mod_headers.c
index 20edf23ae1..cdf14fd8d6 100644
--- a/modules/metadata/mod_headers.c
+++ b/modules/metadata/mod_headers.c
@@ -60,12 +60,13 @@
* mod_headers.c: Add/append/remove HTTP response headers
* Written by Paul Sutton, paul@ukweb.com, 1 Oct 1996
*
- * New directive, Header, can be used to add/replace/remove HTTP headers.
+ * HeaderIn and HeaderOut can be used to add/replace/remove HTTP headers.
* Valid in both per-server and per-dir configurations.
*
* Syntax is:
*
- * Header action header value
+ * HeaderIn action header value
+ * HeaderOut action header value
*
* Where action is one of:
* set - set this header, replacing any old value
@@ -77,8 +78,8 @@
* Where action is unset, the third argument (value) should not be given.
* The header name can include the colon, or not.
*
- * The Header directive can only be used where allowed by the FileInfo
- * override.
+ * The Header(In|Out) directive can only be used where allowed by the
+ * FileInfo override.
*
* When the request is processed, the header directives are processed in
* this order: firstly, the main server, then the virtual server handling
@@ -89,21 +90,22 @@
* the following two directives have different effect if applied in
* the reverse order:
*
- * Header append Author "John P. Doe"
- * Header unset Author
+ * HeaderOut append Author "John P. Doe"
+ * HeaderOut unset Author
*
* Examples:
*
* To set the "Author" header, use
- * Header add Author "John P. Doe"
+ * HeaderOut add Author "John P. Doe"
*
* To remove a header:
- * Header unset Author
+ * HeaderOut unset Author
*
*/
#include "apr.h"
#include "apr_strings.h"
+#include "apr_buckets.h"
#define APR_WANT_STRFUNC
#include "apr_want.h"
@@ -111,7 +113,8 @@
#include "httpd.h"
#include "http_config.h"
#include "http_request.h"
-
+#include "http_log.h"
+#include "util_filter.h"
typedef enum {
hdr_add = 'a', /* add header (could mean multiple hdrs) */
@@ -120,6 +123,11 @@ typedef enum {
hdr_unset = 'u' /* unset header */
} hdr_actions;
+typedef enum {
+ hdr_in = 0, /* HeaderIn */
+ hdr_out = 1, /* HeaderOut */
+} hdr_inout;
+
typedef struct {
hdr_actions action;
char *header;
@@ -131,7 +139,8 @@ typedef struct {
* a per-dir and per-server config
*/
typedef struct {
- apr_array_header_t *headers;
+ apr_array_header_t *fixup_in;
+ apr_array_header_t *fixup_out;
} headers_conf;
module AP_MODULE_DECLARE_DATA headers_module;
@@ -140,7 +149,8 @@ static void *create_headers_config(apr_pool_t *p, server_rec *s)
{
headers_conf *conf = apr_pcalloc(p, sizeof(*conf));
- conf->headers = apr_array_make(p, 2, sizeof(header_entry));
+ conf->fixup_in = apr_array_make(p, 2, sizeof(header_entry));
+ conf->fixup_out = apr_array_make(p, 2, sizeof(header_entry));
return conf;
}
@@ -156,13 +166,15 @@ static void *merge_headers_config(apr_pool_t *p, void *basev, void *overridesv)
headers_conf *base = basev;
headers_conf *overrides = overridesv;
- newconf->headers = apr_array_append(p, base->headers, overrides->headers);
+ newconf->fixup_in = apr_array_append(p, base->fixup_in, overrides->fixup_in);
+ newconf->fixup_out = apr_array_append(p, base->fixup_out, overrides->fixup_out);
return newconf;
}
-static const char *header_cmd(cmd_parms *cmd, void *indirconf,
+/* handle HeaderIn and HeaderOut directive */
+static const char *header_inout_cmd(hdr_inout inout, cmd_parms *cmd, void *indirconf,
const char *action, const char *inhdr,
const char *value)
{
@@ -175,10 +187,10 @@ static const char *header_cmd(cmd_parms *cmd, void *indirconf,
char *colon;
if (cmd->path) {
- new = (header_entry *) apr_array_push(dirconf->headers);
+ new = (header_entry *) apr_array_push((hdr_in == inout) ? dirconf->fixup_in : dirconf->fixup_out);
}
else {
- new = (header_entry *) apr_array_push(serverconf->headers);
+ new = (header_entry *) apr_array_push((hdr_in == inout) ? serverconf->fixup_in : serverconf->fixup_out);
}
if (!strcasecmp(action, "set"))
@@ -194,10 +206,10 @@ static const char *header_cmd(cmd_parms *cmd, void *indirconf,
if (new->action == hdr_unset) {
if (value)
- return "Header unset takes two arguments";
+ return "Header(In|Out) unset takes two arguments";
}
else if (!value)
- return "Header requires three arguments";
+ return "Header(In|Out) requires three arguments";
if ((colon = strchr(hdr, ':')))
*colon = '\0';
@@ -208,54 +220,122 @@ static const char *header_cmd(cmd_parms *cmd, void *indirconf,
return NULL;
}
-static const command_rec headers_cmds[] =
+/* handle deprecated Header directive */
+static const char *header_cmd(cmd_parms *cmd, void *indirconf,
+ const char *action, const char *inhdr,
+ const char *value)
{
- AP_INIT_TAKE23("Header", header_cmd, NULL, OR_FILEINFO,
- "an action, header and value"),
- {NULL}
-};
+ return "The Header directive has been deprecated. Use HeaderOut instead.";
+}
-static void do_headers_fixup(request_rec *r, apr_array_header_t *headers)
+/* handle HeaderOut directive */
+static const char *header_out_cmd(cmd_parms *cmd, void *indirconf,
+ const char *action, const char *inhdr,
+ const char *value)
+{
+ return header_inout_cmd(hdr_out, cmd, indirconf, action, inhdr, value);
+}
+
+/* handle HeaderIn directive */
+static const char *header_in_cmd(cmd_parms *cmd, void *indirconf,
+ const char *action, const char *inhdr,
+ const char *value)
+{
+ return header_inout_cmd(hdr_in, cmd, indirconf, action, inhdr, value);
+}
+
+
+static void do_headers_fixup(apr_table_t *headers,
+ apr_array_header_t *fixup)
{
int i;
- for (i = 0; i < headers->nelts; ++i) {
- header_entry *hdr = &((header_entry *) (headers->elts))[i];
+ for (i = 0; i < fixup->nelts; ++i) {
+ header_entry *hdr = &((header_entry *) (fixup->elts))[i];
switch (hdr->action) {
case hdr_add:
- apr_table_addn(r->headers_out, hdr->header, hdr->value);
+ apr_table_addn(headers, hdr->header, hdr->value);
break;
case hdr_append:
- apr_table_mergen(r->headers_out, hdr->header, hdr->value);
+ apr_table_mergen(headers, hdr->header, hdr->value);
break;
case hdr_set:
- apr_table_setn(r->headers_out, hdr->header, hdr->value);
+ apr_table_setn(headers, hdr->header, hdr->value);
break;
case hdr_unset:
- apr_table_unset(r->headers_out, hdr->header);
+ apr_table_unset(headers, hdr->header);
break;
}
}
+}
+
+static void ap_headers_insert_output_filter(request_rec *r)
+{
+ headers_conf *serverconf = ap_get_module_config(r->server->module_config,
+ &headers_module);
+ headers_conf *dirconf = ap_get_module_config(r->per_dir_config,
+ &headers_module);
+
+ if (serverconf->fixup_out->nelts || dirconf->fixup_out->nelts) {
+ ap_add_output_filter("FIXUP_HEADERS_OUT", NULL, r, r->connection);
+ }
+}
+
+static apr_status_t ap_headers_output_filter(ap_filter_t *f,
+ apr_bucket_brigade *in)
+{
+ headers_conf *serverconf = ap_get_module_config(f->r->server->module_config,
+ &headers_module);
+ headers_conf *dirconf = ap_get_module_config(f->r->per_dir_config,
+ &headers_module);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, f->r->server,
+ "headers: ap_headers_output_filter()");
+
+ /* do the fixup */
+ do_headers_fixup(f->r->headers_out, serverconf->fixup_out);
+ do_headers_fixup(f->r->headers_out, dirconf->fixup_out);
+
+ /* remove ourselves from the filter chain */
+ ap_remove_output_filter(f);
+
+ /* send the data up the stack */
+ return ap_pass_brigade(f->next,in);
}
-static int fixup_headers(request_rec *r)
+static apr_status_t ap_headers_fixup(request_rec *r)
{
headers_conf *serverconf = ap_get_module_config(r->server->module_config,
&headers_module);
headers_conf *dirconf = ap_get_module_config(r->per_dir_config,
&headers_module);
- do_headers_fixup(r, serverconf->headers);
- do_headers_fixup(r, dirconf->headers);
+ /* do the fixup */
+ if (serverconf->fixup_in->nelts || dirconf->fixup_in->nelts) {
+ do_headers_fixup(r->headers_in, serverconf->fixup_in);
+ do_headers_fixup(r->headers_in, dirconf->fixup_in);
+ }
return DECLINED;
}
+
+static const command_rec headers_cmds[] =
+{
+ AP_INIT_TAKE23("Header", header_cmd, NULL, OR_FILEINFO,
+ "deprecated, use HeaderOut instead"),
+ AP_INIT_TAKE23("HeaderIn", header_in_cmd, NULL, OR_FILEINFO,
+ "an action, header and value"),
+ AP_INIT_TAKE23("HeaderOut", header_out_cmd, NULL, OR_FILEINFO,
+ "an action, header and value"),
+ {NULL}
+};
static void register_hooks(apr_pool_t *p)
{
- ap_hook_fixups(fixup_headers, NULL, NULL, APR_HOOK_MIDDLE);
-}
+ ap_hook_insert_filter(ap_headers_insert_output_filter, NULL, NULL, APR_HOOK_LAST);
+ ap_hook_fixups(ap_headers_fixup, NULL, NULL, APR_HOOK_LAST);
+ ap_register_output_filter("FIXUP_HEADERS_OUT", ap_headers_output_filter, AP_FTYPE_CONTENT);
+}
module AP_MODULE_DECLARE_DATA headers_module =
{