diff options
author | Bill Stoddard <stoddard@apache.org> | 2001-05-19 22:12:05 +0200 |
---|---|---|
committer | Bill Stoddard <stoddard@apache.org> | 2001-05-19 22:12:05 +0200 |
commit | cd1eca7994c7db23eb305523032e34f097edb740 (patch) | |
tree | d049f76f155afe581ca390619c99d58c9856e9f7 /modules/metadata | |
parent | Fix function type to match hook declaration. (diff) | |
download | apache2-cd1eca7994c7db23eb305523032e34f097edb740.tar.xz apache2-cd1eca7994c7db23eb305523032e34f097edb740.zip |
Reimplement mod_headers as an output filter. mod_headers can now
add custom headers to inbound requests using the HeaderIn directive
and to responses using the HeaderOut directive. The Header
directive has been deprecated in favor of the HeaderOut directive.
Submitted by: Graham Leggett
Reviewed by: Bill Stoddard
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@89165 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules/metadata')
-rw-r--r-- | modules/metadata/mod_headers.c | 148 |
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 = { |