mod_headers.c revision 89ea31761658f422cf21cd3b0224dc5fe95cccd3
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein/* Copyright 1999-2004 The Apache Software Foundation
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Licensed under the Apache License, Version 2.0 (the "License");
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * you may not use this file except in compliance with the License.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * You may obtain a copy of the License at
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Unless required by applicable law or agreed to in writing, software
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * distributed under the License is distributed on an "AS IS" BASIS,
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * See the License for the specific language governing permissions and
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * limitations under the License.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * mod_headers.c: Add/append/remove HTTP response headers
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Written by Paul Sutton, paul@ukweb.com, 1 Oct 1996
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * The Header directive can be used to add/replace/remove HTTP headers
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * within the response message. The RequestHeader directive can be used
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * to add/replace/remove HTTP headers before a request message is processed.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Valid in both per-server and per-dir configurations.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Syntax is:
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Header action header value
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * RequestHeader action header value
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Where action is one of:
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * set - set this header, replacing any old value
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * add - add this header, possible resulting in two or more
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * headers with the same name
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * append - append this text onto any existing header of this same
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * unset - remove this header
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Where action is unset, the third argument (value) should not be given.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * The header name can include the colon, or not.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * The Header and RequestHeader directives can only be used where allowed
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * by the FileInfo override.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * When the request is processed, the header directives are processed in
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * this order: firstly, the main server, then the virtual server handling
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * this request (if any), then any <Directory> sections (working downwards
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * from the root dir), then an <Location> sections (working down from
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * shortest URL component), the any <File> sections. This order is
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * important if any 'set' or 'unset' actions are used. For example,
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * the following two directives have different effect if applied in
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * the reverse order:
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Header append Author "John P. Doe"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Header unset Author
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Examples:
f4c310fd2555c6faca1f980f00b161eadb089023gstein * To set the "Author" header, use
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Header add Author "John P. Doe"
1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94agstein * To remove a header:
8a46775d163c06a8c51d1b0a3f2edfde945cb1d8stoddard * Header unset Author
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "mod_ssl.h" /* for the ssl_var_lookup optional function defn */
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* format_tag_hash is initialized during pre-config */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmtypedef enum {
f4c310fd2555c6faca1f980f00b161eadb089023gstein hdr_add = 'a', /* add header (could mean multiple hdrs) */
f4c310fd2555c6faca1f980f00b161eadb089023gstein hdr_append = 'm', /* append (merge into any old value) */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein hdr_echo = 'e' /* echo headers from request to response */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gsteintypedef enum {
f4c310fd2555c6faca1f980f00b161eadb089023gstein * There is an array of struct format_tag per Header/RequestHeader
707ecf9559338ec06b24334bc9abcca670325cc4gstein * config directive
707ecf9559338ec06b24334bc9abcca670325cc4gsteintypedef struct {
f4c310fd2555c6faca1f980f00b161eadb089023gstein * There is one "header_entry" per Header/RequestHeader config directive
707ecf9559338ec06b24334bc9abcca670325cc4gsteintypedef struct {
707ecf9559338ec06b24334bc9abcca670325cc4gstein apr_array_header_t *ta; /* Array of format_tag structs */
707ecf9559338ec06b24334bc9abcca670325cc4gstein/* echo_do is used for Header echo to iterate through the request headers*/
707ecf9559338ec06b24334bc9abcca670325cc4gsteintypedef struct {
707ecf9559338ec06b24334bc9abcca670325cc4gstein * headers_conf is our per-module configuration. This is used as both
707ecf9559338ec06b24334bc9abcca670325cc4gstein * a per-dir and per-server config
707ecf9559338ec06b24334bc9abcca670325cc4gsteintypedef struct {
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein/* Pointer to ssl_var_lookup, if available. */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *header_ssl_lookup = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Tag formatting functions
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *constant_item(request_rec *r, char *stuff)
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *header_request_duration(request_rec *r, char *a)
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *header_request_time(request_rec *r, char *a)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return apr_psprintf(r->pool, "t=%" APR_TIME_T_FMT, r->request_time);
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* unwrap_header returns HDR with any newlines converted into
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein * whitespace if necessary. */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *unwrap_header(apr_pool_t *p, const char *hdr)
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ap_strchr_c(hdr, APR_ASCII_LF) || ap_strchr_c(hdr, APR_ASCII_CR)) {
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein } while (*ptr++);
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gsteinstatic const char *header_request_env_var(request_rec *r, char *a)
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein return "(null)";
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gsteinstatic const char *header_request_ssl_var(request_rec *r, char *name)
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein const char *val = header_ssl_lookup(r->pool, r->server,
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein return "(null)";
f4c310fd2555c6faca1f980f00b161eadb089023gstein return "(null)";
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein * Config routines
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gsteinstatic void *create_headers_config(apr_pool_t *p, server_rec *s)
f4c310fd2555c6faca1f980f00b161eadb089023gstein conf->fixup_in = apr_array_make(p, 2, sizeof(header_entry));
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm conf->fixup_out = apr_array_make(p, 2, sizeof(header_entry));
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm conf->fixup_err = apr_array_make(p, 2, sizeof(header_entry));
f94aab38f6ee899f463f0118ea395291f7c5b4cegsteinstatic void *create_headers_dir_config(apr_pool_t *p, char *d)
707ecf9559338ec06b24334bc9abcca670325cc4gsteinstatic void *merge_headers_config(apr_pool_t *p, void *basev, void *overridesv)
f4c310fd2555c6faca1f980f00b161eadb089023gstein headers_conf *newconf = apr_pcalloc(p, sizeof(*newconf));
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm newconf->fixup_in = apr_array_append(p, base->fixup_in, overrides->fixup_in);
f4c310fd2555c6faca1f980f00b161eadb089023gstein newconf->fixup_out = apr_array_append(p, base->fixup_out, overrides->fixup_out);
f4c310fd2555c6faca1f980f00b161eadb089023gstein newconf->fixup_err = apr_array_append(p, base->fixup_err,
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic char *parse_misc_string(apr_pool_t *p, format_tag *tag, const char **sa)
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (*s && *s != '%') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein * This might allocate a few chars extra if there's a backslash
f4c310fd2555c6faca1f980f00b161eadb089023gstein * escape in the format string.
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (*s && *s != '%') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (*s != '\\') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d++ = *s++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein switch (*s) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d++ = '\\';
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d++ = '\r';
f71d4ec448449837beefe21cf7c9f8d9b6bd4654gstein *d++ = '\n';
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d++ = '\t';
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* copy verbatim */
f71d4ec448449837beefe21cf7c9f8d9b6bd4654gstein *d++ = '\\';
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Allow the loop to deal with this *s in the normal
f4c310fd2555c6faca1f980f00b161eadb089023gstein * fashion so that it handles end of string etc.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * properly.
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic char *parse_format_tag(apr_pool_t *p, format_tag *tag, const char **sa)
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm const char *s = *sa;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Handle string literal/conditionals */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (*s != '%') {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm s++; /* skip the % */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* grab the argument if there is one */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (*s == '{') {
1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94agstein tag_handler = (const char * (*)(request_rec *,char *))apr_hash_get(format_tag_hash, s++, 1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return apr_pstrcat(p, "Unrecognized Header or RequestHeader directive %",
f4c310fd2555c6faca1f980f00b161eadb089023gstein * A format string consists of white space, text and optional format
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * tags in any order. E.g.,
1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94agstein * Header add MyHeader "Free form text %D %t more text"
1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94agstein * Decompose the format string into its tags. Each tag (struct format_tag)
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * contains a pointer to the function used to format the tag. Then save each
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * tag in the tag array anchored in the header_entry.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic char *parse_format_string(apr_pool_t *p, header_entry *hdr, const char *s)
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* No string to parse with unset and copy commands */
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (*s) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((res = parse_format_tag(p, (format_tag *) apr_array_push(hdr->ta), &s))) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm/* handle RequestHeader and Header directive */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *header_inout_cmd(hdr_inout inout, cmd_parms *cmd,
f4c310fd2555c6faca1f980f00b161eadb089023gstein headers_conf *serverconf = ap_get_module_config(s->module_config,
f4c310fd2555c6faca1f980f00b161eadb089023gstein return "first argument must be add, set, append, unset or echo.";
f4c310fd2555c6faca1f980f00b161eadb089023gstein return "header unset takes two arguments";
f4c310fd2555c6faca1f980f00b161eadb089023gstein return "Header echo takes two arguments";
f4c310fd2555c6faca1f980f00b161eadb089023gstein return "Header echo only valid on Header directive";
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm regex = ap_pregcomp(cmd->pool, hdr, REG_EXTENDED | REG_NOSUB);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return "Header echo regex could not be compiled";
f4c310fd2555c6faca1f980f00b161eadb089023gstein return "header requires three arguments";
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Handle the envclause on Header */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return "error: envclause should be in the form env=envar";
f4c310fd2555c6faca1f980f00b161eadb089023gstein || ((envclause[4] == '!') && (envclause[5] == '\0'))) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return "error: missing environment variable name. "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "envclause should be in the form env=envar ";
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm condition_var = apr_pstrdup(cmd->pool, &envclause[4]);
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Handle all (xxx)Header directives */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *header_cmd(cmd_parms *cmd, void *indirconf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *args)
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *action;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *hdr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *val;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *envclause;
f4c310fd2555c6faca1f980f00b161eadb089023gstein envclause = *s ? ap_getword_conf(cmd->pool, &s) : NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return header_inout_cmd(outbl, cmd, indirconf, action, hdr, val, envclause);
5646ba89a25a695006edae46de226fb57a2e6270gstein * Process the tags in the format string. Tags may be format specifiers
f4c310fd2555c6faca1f980f00b161eadb089023gstein * (%D, %t, etc.), whitespace or text strings. For each tag, run the handler
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * (formatter) specific to the tag. Handlers return text strings.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Concatenate the return from each handler into one string that is
f4c310fd2555c6faca1f980f00b161eadb089023gstein * returned from this call.
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic char* process_tags(header_entry *hdr, request_rec *r)
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein const char *s;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int echo_header(echo_do *v, const char *key, const char *val)
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If the input header (key) matches the regex, echo it intact to
f4c310fd2555c6faca1f980f00b161eadb089023gstein * r->headers_out.
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void do_headers_fixup(request_rec *r, hdr_inout inout,
f4c310fd2555c6faca1f980f00b161eadb089023gstein header_entry *hdr = &((header_entry *) (fixup->elts))[i];
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Have any conditional envar-controlled Header processing to do? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (apr_table_get(r->subprocess_env, &envar[1]) != NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_table_addn(headers, hdr->header, process_tags(hdr, r));
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_table_mergen(headers, hdr->header, process_tags(hdr, r));
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_table_setn(headers, hdr->header, process_tags(hdr, r));
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_table_do((int (*) (void *, const char *, const char *))
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void ap_headers_insert_output_filter(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein headers_conf *serverconf = ap_get_module_config(r->server->module_config,
f4c310fd2555c6faca1f980f00b161eadb089023gstein headers_conf *dirconf = ap_get_module_config(r->per_dir_config,
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (serverconf->fixup_out->nelts || dirconf->fixup_out->nelts
f4c310fd2555c6faca1f980f00b161eadb089023gstein || serverconf->fixup_err->nelts || dirconf->fixup_err->nelts) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_add_output_filter("FIXUP_HEADERS_OUT", NULL, r, r->connection);
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Make sure our error-path filter is in place.
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void ap_headers_insert_error_filter(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein headers_conf *serverconf = ap_get_module_config(r->server->module_config,
f4c310fd2555c6faca1f980f00b161eadb089023gstein headers_conf *dirconf = ap_get_module_config(r->per_dir_config,
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (serverconf->fixup_err->nelts || dirconf->fixup_err->nelts) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_add_output_filter("FIXUP_HEADERS_ERR", NULL, r, r->connection);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic apr_status_t ap_headers_output_filter(ap_filter_t *f,
f4c310fd2555c6faca1f980f00b161eadb089023gstein headers_conf *serverconf = ap_get_module_config(f->r->server->module_config,
33397e35239f202a595837571561468f02b2e806gstein headers_conf *dirconf = ap_get_module_config(f->r->per_dir_config,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, f->r->server,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "headers: ap_headers_output_filter()");
49bf4df23d9e5281abcd83005550bda818b17b08wrowe /* do the fixup */
f4c310fd2555c6faca1f980f00b161eadb089023gstein do_headers_fixup(f->r, hdr_err, serverconf->fixup_err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein do_headers_fixup(f->r, hdr_out, serverconf->fixup_out);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* remove ourselves from the filter chain */
ba2ad3b1bb4a729278ad8e8846d34ddd27b6551cgstein /* send the data up the stack */
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Make sure we propagate any ErrorHeader settings on the error
f4c310fd2555c6faca1f980f00b161eadb089023gstein * path through http_protocol.c.
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic apr_status_t ap_headers_error_filter(ap_filter_t *f,
f4c310fd2555c6faca1f980f00b161eadb089023gstein serverconf = ap_get_module_config(f->r->server->module_config,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, f->r->server,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "headers: ap_headers_error_filter()");
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Add any header fields defined by ErrorHeader to r->err_headers_out.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Server-wide first, then per-directory to allow overriding.
f4c310fd2555c6faca1f980f00b161eadb089023gstein do_headers_fixup(f->r, hdr_err, serverconf->fixup_err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein * We've done our bit; remove ourself from the filter chain so there's
ba2ad3b1bb4a729278ad8e8846d34ddd27b6551cgstein * no possibility we'll be called again.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * Pass the buck. (euro?)
f4c310fd2555c6faca1f980f00b161eadb089023gstein headers_conf *serverconf = ap_get_module_config(r->server->module_config,
f4c310fd2555c6faca1f980f00b161eadb089023gstein headers_conf *dirconf = ap_get_module_config(r->per_dir_config,
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* do the fixup */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (serverconf->fixup_in->nelts || dirconf->fixup_in->nelts) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein AP_INIT_RAW_ARGS("Header", header_cmd, (void *)hdr_out, OR_FILEINFO,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "an action, header and value followed by optional env "
f4c310fd2555c6faca1f980f00b161eadb089023gstein AP_INIT_RAW_ARGS("RequestHeader", header_cmd, (void *)hdr_in, OR_FILEINFO,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "an action, header and value followed by optional env "
f4c310fd2555c6faca1f980f00b161eadb089023gstein AP_INIT_RAW_ARGS("ErrorHeader", header_cmd, (void *)hdr_err, OR_FILEINFO,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "an action, header and value followed by optional env "
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void register_format_tag_handler(apr_pool_t *p, char *tag, void *tag_handler, int def)
f4c310fd2555c6faca1f980f00b161eadb089023gstein const void *h = apr_palloc(p, sizeof(h));
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int header_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
f4c310fd2555c6faca1f980f00b161eadb089023gstein register_format_tag_handler(p, "D", (void*) header_request_duration, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein register_format_tag_handler(p, "t", (void*) header_request_time, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein register_format_tag_handler(p, "e", (void*) header_request_env_var, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein register_format_tag_handler(p, "s", (void*) header_request_ssl_var, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int header_post_config(apr_pool_t *pconf, apr_pool_t *plog,
f4c310fd2555c6faca1f980f00b161eadb089023gstein header_ssl_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_register_output_filter("FIXUP_HEADERS_OUT", ap_headers_output_filter,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_register_output_filter("FIXUP_HEADERS_ERR", ap_headers_error_filter,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_hook_pre_config(header_pre_config,NULL,NULL,APR_HOOK_MIDDLE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_hook_post_config(header_post_config,NULL,NULL,APR_HOOK_MIDDLE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_hook_insert_filter(ap_headers_insert_output_filter, NULL, NULL, APR_HOOK_LAST);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm ap_hook_insert_error_filter(ap_headers_insert_error_filter,
ba2ad3b1bb4a729278ad8e8846d34ddd27b6551cgstein ap_hook_fixups(ap_headers_fixup, NULL, NULL, APR_HOOK_LAST);
f4c310fd2555c6faca1f980f00b161eadb089023gstein merge_headers_config, /* dir merger --- default is to override */