mod_headers.c revision ef5650b61a8e35f3cc93ec07e73efc17ea329894
545f1a3ee91056d6de32adab10c2eab26db89f27dpejesh/* Copyright 1999-2005 The Apache Software Foundation or its licensors, as
545f1a3ee91056d6de32adab10c2eab26db89f27dpejesh * applicable.
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * Licensed under the Apache License, Version 2.0 (the "License");
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * you may not use this file except in compliance with the License.
545f1a3ee91056d6de32adab10c2eab26db89f27dpejesh * You may obtain a copy of the License at
96ad5d81ee4a2cc66a4ae19893efc8aa6d06fae7jailletc * Unless required by applicable law or agreed to in writing, software
7add1372edb1ee95a2c4d1314df4c7567bda7c62jim * distributed under the License is distributed on an "AS IS" BASIS,
7add1372edb1ee95a2c4d1314df4c7567bda7c62jim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * See the License for the specific language governing permissions and
2e545ce2450a9953665f701bb05350f0d3f26275nd * limitations under the License.
5a58787efeb02a1c3f06569d019ad81fd2efa06end * mod_headers.c: Add/append/remove HTTP response headers
af33a4994ae2ff15bc67d19ff1a7feb906745bf8rbowen * Written by Paul Sutton, paul@ukweb.com, 1 Oct 1996
7add1372edb1ee95a2c4d1314df4c7567bda7c62jim * The Header directive can be used to add/replace/remove HTTP headers
7add1372edb1ee95a2c4d1314df4c7567bda7c62jim * within the response message. The RequestHeader directive can be used
5a58787efeb02a1c3f06569d019ad81fd2efa06end * to add/replace/remove HTTP headers before a request message is processed.
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * Valid in both per-server and per-dir configurations.
7add1372edb1ee95a2c4d1314df4c7567bda7c62jim * Syntax is:
00b49f91367894cf867206991ff1373cfeabb759gryzor * Header action header value
7f5b59ccc63c0c0e3e678a168f09ee6a2f51f9d0nd * RequestHeader action header value
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung * Where action is one of:
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd * set - set this header, replacing any old value
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd * add - add this header, possible resulting in two or more
aaf7b7f4cc1be050310c3d7f48bce0ec67e174e4nd * headers with the same name
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * append - append this text onto any existing header of this same
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * unset - remove this header
9a58dc6a2b26ec128b1270cf48810e705f1a90dbsf * Where action is unset, the third argument (value) should not be given.
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * The header name can include the colon, or not.
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * The Header and RequestHeader directives can only be used where allowed
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * by the FileInfo override.
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * When the request is processed, the header directives are processed in
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * this order: firstly, the main server, then the virtual server handling
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * this request (if any), then any <Directory> sections (working downwards
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * from the root dir), then an <Location> sections (working down from
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * shortest URL component), the any <File> sections. This order is
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * important if any 'set' or 'unset' actions are used. For example,
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * the following two directives have different effect if applied in
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * the reverse order:
5a58787efeb02a1c3f06569d019ad81fd2efa06end * Header append Author "John P. Doe"
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * Header unset Author
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * Examples:
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh * To set the "Author" header, use
7add1372edb1ee95a2c4d1314df4c7567bda7c62jim * Header add Author "John P. Doe"
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * To remove a header:
aaf7b7f4cc1be050310c3d7f48bce0ec67e174e4nd * Header unset Author
aaf7b7f4cc1be050310c3d7f48bce0ec67e174e4nd#include "mod_ssl.h" /* for the ssl_var_lookup optional function defn */
4126704c4950bfd46d32ad54e3b106ac6d868a73sf/* format_tag_hash is initialized during pre-config */
4126704c4950bfd46d32ad54e3b106ac6d868a73sftypedef enum {
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen hdr_add = 'a', /* add header (could mean multiple hdrs) */
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen hdr_append = 'm', /* append (merge into any old value) */
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen hdr_echo = 'e' /* echo headers from request to response */
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * magic cmd->info values
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * There is an array of struct format_tag per Header/RequestHeader
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * config directive
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowentypedef struct {
545f1a3ee91056d6de32adab10c2eab26db89f27dpejesh/* 'Magic' condition_var value to run action in post_read_request */
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * There is one "header_entry" per Header/RequestHeader config directive
545f1a3ee91056d6de32adab10c2eab26db89f27dpejeshtypedef struct {
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen const char *header;
545f1a3ee91056d6de32adab10c2eab26db89f27dpejesh apr_array_header_t *ta; /* Array of format_tag structs */
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen/* echo_do is used for Header echo to iterate through the request headers*/
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowentypedef struct {
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * headers_conf is our per-module configuration. This is used as both
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * a per-dir and per-server config
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowentypedef struct {
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen/* Pointer to ssl_var_lookup, if available. */
aaf7b7f4cc1be050310c3d7f48bce0ec67e174e4ndstatic APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *header_ssl_lookup = NULL;
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * Tag formatting functions
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowenstatic const char *constant_item(request_rec *r, char *stuff)
545f1a3ee91056d6de32adab10c2eab26db89f27dpejeshstatic const char *header_request_duration(request_rec *r, char *a)
4aa603e6448b99f9371397d439795c91a93637eandstatic const char *header_request_time(request_rec *r, char *a)
bbcc277fef0330ac4c1f937cb0dea78248225c0ahumbedooh return apr_psprintf(r->pool, "t=%" APR_TIME_T_FMT, r->request_time);
aaf7b7f4cc1be050310c3d7f48bce0ec67e174e4nd/* unwrap_header returns HDR with any newlines converted into
545f1a3ee91056d6de32adab10c2eab26db89f27dpejesh * whitespace if necessary. */
db99fa79ac42b9cc42b63386eb289aecb0f3cb9cndstatic const char *unwrap_header(apr_pool_t *p, const char *hdr)
bf082801b4063fe22a99661889cbd9a7701dae9fnd if (ap_strchr_c(hdr, APR_ASCII_LF) || ap_strchr_c(hdr, APR_ASCII_CR)) {
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen } while (*ptr++);
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowenstatic const char *header_request_env_var(request_rec *r, char *a)
4aa603e6448b99f9371397d439795c91a93637eand return "(null)";
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowenstatic const char *header_request_ssl_var(request_rec *r, char *name)
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen const char *val = header_ssl_lookup(r->pool, r->server,
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen return "(null)";
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen return "(null)";
c35acdcbd4d173d3c536cf0be1295fa6c510cf8drbowen * Config routines
7add1372edb1ee95a2c4d1314df4c7567bda7c62jimstatic void *create_headers_dir_config(apr_pool_t *p, char *d)
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung conf->fixup_in = apr_array_make(p, 2, sizeof(header_entry));
727872d18412fc021f03969b8641810d8896820bhumbedooh conf->fixup_out = apr_array_make(p, 2, sizeof(header_entry));
0d0ba3a410038e179b695446bb149cce6264e0abnd conf->fixup_err = apr_array_make(p, 2, sizeof(header_entry));
727872d18412fc021f03969b8641810d8896820bhumbedoohstatic void *merge_headers_config(apr_pool_t *p, void *basev, void *overridesv)
0d0ba3a410038e179b695446bb149cce6264e0abnd headers_conf *newconf = apr_pcalloc(p, sizeof(*newconf));
727872d18412fc021f03969b8641810d8896820bhumbedooh newconf->fixup_out = apr_array_append(p, base->fixup_out,
0d0ba3a410038e179b695446bb149cce6264e0abnd newconf->fixup_err = apr_array_append(p, base->fixup_err,
7fec19672a491661b2fe4b29f685bc7f4efa64d4ndstatic char *parse_misc_string(apr_pool_t *p, format_tag *tag, const char **sa)
5a58787efeb02a1c3f06569d019ad81fd2efa06end const char *s;
s = *sa;
s = *sa;
*sa = s;
return NULL;
const char *s = *sa;
/* Handle string literal/conditionals */
*sa = ++s;
return NULL;
if (!tag_handler) {
*sa = s;
return NULL;
char *res;
return NULL;
return res;
return NULL;
void *indirconf,
const char *action,
const char *hdr,
const char *value,
const char* envclause)
const char *colon;
if (value) {
if (envclause) {
if (value) {
if (envclause) {
else if (!value)
const char *args)
const char *action;
const char *hdr;
const char *val;
const char *envclause;
if (*args) {
case hdr_add:
case hdr_append:
case hdr_set:
case hdr_unset:
case hdr_echo:
echo_do v;
apr_table_do((int (*) (void *, const char *, const char *))
* path through http_protocol.c.
return DECLINED;
return DECLINED;
{NULL}
const void *tag_handler)
return OK;
return OK;