]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Fix regression from 1.3:
authorAndré Malo <nd@apache.org>
Thu, 19 Aug 2004 22:53:13 +0000 (22:53 +0000)
committerAndré Malo <nd@apache.org>
Thu, 19 Aug 2004 22:53:13 +0000 (22:53 +0000)
There's a new optional flag for the Header directive
('always'), which keeps the former ErrorHeader functionality.

The opposite flag to 'always' is 'onsuccess'. So the new directives
are written as:

Header set foo bar
# which is the same as
Header onsuccess set foo bar
# and a subset of
Header always set foo bar
# which is what the ErrorHeader directive did.

PR: 28657
Obtained from: 2.1
Reviewed by: Brad Nicholes, Joe Orton

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/APACHE_2_0_BRANCH@104732 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
STATUS
docs/manual/mod/mod_headers.xml
docs/manual/upgrading.xml
modules/metadata/mod_headers.c

diff --git a/CHANGES b/CHANGES
index d1702bedd1f5a6b7d646acda57eabb8336bc895f..25caa0861a503441d5efb8d6ccc1815f7ae2a2af 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,11 @@
 Changes with Apache 2.0.51
 
+  *) Backport from 2.1 / Regression from 1.3: mod_headers now knows
+     again the functionality of the ErrorHeader directive. But instead
+     using this misnomer additional flags to the Header directive were
+     introduced ("always" and "onsuccess", defaulting to the latter).
+     PR 28657.  [André Malo]
+
   *) Use the higher performing 'httpready' Accept Filter on all platforms 
      except FreeBSD < 4.1.1. [Paul Querna]
 
diff --git a/STATUS b/STATUS
index 38778ae98ad3dd1a6a9cd663fd097930d1d676c9..21e8c3ae1fa72c3de5df44e6d3d2a75d45c17022 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -1,5 +1,5 @@
 APACHE 2.0 STATUS:                                              -*-text-*-
-Last modified at [$Date: 2004/08/19 18:55:47 $]
+Last modified at [$Date: 2004/08/19 22:53:12 $]
 
 Release:
 
@@ -213,13 +213,6 @@ PATCHES TO BACKPORT FROM 2.1
          server/config.c: r1.175
        +1: nd
 
-    *) mod_headers: Regression from 1.3: There's no ErrorHeader directive.
-       Since this was always a misnomer, it was dropped in 2.1 and
-       Header was extended instead. Backport this from 2.1 and document
-       this in the upgrading docs. A 2.0 patch is here:
-         http://www.apache.org/~nd/header_always_2.0.diff
-       +1: nd, bnicholes, jorton
-
     *) mod_rewrite: Fix confused map cache (with maps in different VHs using
        the same name). PR 26462. (2.0 + 1.3)
        A patch for 1.3 is here (2.0 goes similar):
index 4ff09f1a299aae719cd32115142c3a88039b15b6..d086627ca4b26835d5f7eb67878f4e4e217f1530 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">
 <?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
-<!-- $Revision: 1.5.2.5 $ -->
+<!-- $Revision: 1.5.2.6 $ -->
 
 <!--
  Copyright 2002-2004 The Apache Software Foundation
@@ -194,17 +194,28 @@ is available only in Apache 2.0</compatibility>
 <directivesynopsis>
 <name>Header</name>
 <description>Configure HTTP response headers</description>
-<syntax>Header set|append|add|unset|echo  <var>header</var>
-[<var>value</var> [env=[!]<var>variable</var>]]</syntax>
+<syntax>Header [<var>condition</var>] set|append|add|unset|echo
+<var>header</var> [<var>value</var>] [env=[!]<var>variable</var>]</syntax>
 <contextlist><context>server config</context><context>virtual host</context>
 <context>directory</context><context>.htaccess</context></contextlist>
 <override>FileInfo</override>
+<compatibility><var>Condition</var> is available in version 2.0.51 and
+later</compatibility>
 
 <usage>
     <p>This directive can replace, merge or remove HTTP response
     headers. The header is modified just after the content handler
     and output filters are run, allowing outgoing headers to be
-    modified. The action it performs is determined by the first
+    modified.</p>
+
+    <p>The optional <var>condition</var> can be either <code>onsuccess</code>
+    or <code>always</code>. It determines, which internal header table should be
+    operated on. <code>onsuccess</code> stands for <code>2<var>xx</var></code>
+    status codes and <code>always</code> for all status codes (including
+    <code>2<var>xx</var></code>). Especially if you want to unset headers
+    set by certain modules, you should try out, which table is affected.</p>
+
+    <p>The action it performs is determined by the second
     argument. This can be one of the following values:</p>
 
     <dl>
index 819dea82c65be332c879ef1b9d55ee660634b0bb..272cf8cf188a2a2dcaad97a11bbf0577145f8ce0 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version='1.0' encoding='UTF-8' ?>
 <!DOCTYPE manualpage SYSTEM "./style/manualpage.dtd">
 <?xml-stylesheet type="text/xsl" href="./style/manual.en.xsl"?>
-<!-- $Revision: 1.6.2.8 $ -->
+<!-- $Revision: 1.6.2.9 $ -->
 
 <!--
  Copyright 2002-2004 The Apache Software Foundation
@@ -169,6 +169,16 @@ Apache 2.0</a></seealso>
       files.  The old behavior can be restored using the <directive
       module="mod_mime">MultiviewsMatch</directive> directive.</li>
 
+      <li>(<em>since version 2.0.51</em>)
+      <p>The functionality of the <code>ErrorHeader</code> directive was
+      put together with the <directive module="mod_headers">Header</directive>
+      directive, since it was a misnomer. Use</p>
+
+      <example>
+        Header always set foo bar
+      </example>
+
+      <p>instead to get the desired bahviour.</p></li>
     </ul>
   </section>
 
index 306fa5b66041fdb47fc06a2f7e17b4325688b4d0..7279f93b360048c712e0e447cc42a485f29a68c6 100644 (file)
@@ -76,6 +76,7 @@
 #include "http_request.h"
 #include "http_log.h"
 #include "util_filter.h"
+#include "http_protocol.h" /* ap_hook_insert_error_filter */
 
 /* format_tag_hash is initialized during pre-config */
 static apr_hash_t *format_tag_hash;
@@ -88,10 +89,12 @@ typedef enum {
     hdr_echo = 'e'              /* echo headers from request to response */
 } hdr_actions;
 
-typedef enum {
-    hdr_in = 0,                 /* RequestHeader */
-    hdr_out = 1                 /* Header */
-} hdr_inout;
+/*
+ * magic cmd->info values
+ */
+static char hdr_in  = '0';  /* RequestHeader */
+static char hdr_out = '1';  /* Header onsuccess */
+static char hdr_err = '2';  /* Header always */
 
 /*
  * There is an array of struct format_tag per Header/RequestHeader 
@@ -126,6 +129,7 @@ typedef struct {
 typedef struct {
     apr_array_header_t *fixup_in;
     apr_array_header_t *fixup_out;
+    apr_array_header_t *fixup_err;
 } headers_conf;
 
 module AP_MODULE_DECLARE_DATA headers_module;
@@ -158,29 +162,26 @@ static const char *header_request_env_var(request_rec *r, char *a)
 /*
  * Config routines
  */
-static void *create_headers_config(apr_pool_t *p, server_rec *s)
+static void *create_headers_config(apr_pool_t *p, char *dummy)
 {
-    headers_conf *conf = apr_pcalloc(p, sizeof(*conf));
+    headers_conf *conf = apr_palloc(p, sizeof(*conf));
 
     conf->fixup_in = apr_array_make(p, 2, sizeof(header_entry));
     conf->fixup_out = apr_array_make(p, 2, sizeof(header_entry));
+    conf->fixup_err = apr_array_make(p, 2, sizeof(header_entry));
 
     return conf;
 }
 
-static void *create_headers_dir_config(apr_pool_t *p, char *d)
-{
-    return create_headers_config(p, NULL);
-}
-
 static void *merge_headers_config(apr_pool_t *p, void *basev, void *overridesv)
 {
-    headers_conf *newconf = apr_pcalloc(p, sizeof(*newconf));
+    headers_conf *newconf = apr_palloc(p, sizeof(*newconf));
     headers_conf *base = basev;
     headers_conf *overrides = overridesv;
 
     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);
+    newconf->fixup_err = apr_array_append(p, base->fixup_err, overrides->fixup_err);
 
     return newconf;
 }
@@ -317,17 +318,12 @@ static const char *header_inout_cmd(cmd_parms *cmd, void *indirconf,
     char *colon;
     char *hdr = apr_pstrdup(cmd->pool, inhdr);
     header_entry *new;
-    server_rec *s = cmd->server;
-    headers_conf *serverconf = ap_get_module_config(s->module_config,
-                                                    &headers_module);
-    hdr_inout inout = (hdr_inout)cmd->info;
+    apr_array_header_t *fixup = (cmd->info == &hdr_in)
+        ? dirconf->fixup_in   : (cmd->info == &hdr_err)
+        ? dirconf->fixup_err
+        : dirconf->fixup_out;
 
-    if (cmd->path) {
-        new = (header_entry *) apr_array_push((hdr_in == inout) ? dirconf->fixup_in : dirconf->fixup_out);
-    }
-    else {
-        new = (header_entry *) apr_array_push((hdr_in == inout) ? serverconf->fixup_in : serverconf->fixup_out);
-    }
+    new = (header_entry *) apr_array_push(fixup);
 
     if (!strcasecmp(action, "set"))
         new->action = hdr_set;
@@ -350,7 +346,7 @@ static const char *header_inout_cmd(cmd_parms *cmd, void *indirconf,
         regex_t *regex;
         if (value)
             return "Header echo takes two arguments";
-        else if (inout != hdr_out)
+        else if (cmd->info == &hdr_in)
             return "Header echo only valid on Header directive";
         else {
             regex = ap_pregcomp(cmd->pool, hdr, REG_EXTENDED | REG_NOSUB);
@@ -396,10 +392,24 @@ static const char *header_cmd(cmd_parms *cmd, void *indirconf,
 
     s = apr_pstrdup(cmd->pool, args);
     action = ap_getword_conf(cmd->pool, &s);
+    if (cmd->info == &hdr_out) {
+        if (!strcasecmp(action, "always")) {
+            cmd->info = &hdr_err;
+            action = ap_getword_conf(cmd->pool, &s);
+        }
+        else if (!strcasecmp(action, "onsuccess")) {
+            action = ap_getword_conf(cmd->pool, &s);
+        }
+    }
     hdr = ap_getword_conf(cmd->pool, &s);
     val = *s ? ap_getword_conf(cmd->pool, &s) : NULL;
     envclause = *s ? ap_getword_conf(cmd->pool, &s) : NULL;
 
+    if (*s) {
+        return apr_pstrcat(cmd->pool, cmd->cmd->name,
+                           " has too many arguments", NULL);
+    }
+
     return header_inout_cmd(cmd, indirconf, action, hdr, val, envclause);
 }
 
@@ -440,11 +450,10 @@ static int echo_header(echo_do *v, const char *key, const char *val)
     return 1;
 }
 
-static void do_headers_fixup(request_rec *r, hdr_inout inout,
+static void do_headers_fixup(request_rec *r, apr_table_t *headers,
                              apr_array_header_t *fixup)
 {
     int i;
-    apr_table_t *headers = (hdr_in == inout) ? r->headers_in : r->headers_out;
 
     for (i = 0; i < fixup->nelts; ++i) {
         header_entry *hdr = &((header_entry *) (fixup->elts))[i];
@@ -490,21 +499,27 @@ static void do_headers_fixup(request_rec *r, hdr_inout inout,
 
 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) {
+    if (dirconf->fixup_out->nelts || dirconf->fixup_err->nelts) {
         ap_add_output_filter("FIXUP_HEADERS_OUT", NULL, r, r->connection);
     }
 }
 
+static void ap_headers_insert_error_filter(request_rec *r)
+{
+    headers_conf *dirconf = ap_get_module_config(r->per_dir_config,
+                                                 &headers_module);
+
+    if (dirconf->fixup_err->nelts) {
+        ap_add_output_filter("FIXUP_HEADERS_ERR", 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);
 
@@ -512,8 +527,27 @@ static apr_status_t ap_headers_output_filter(ap_filter_t *f,
                  "headers: ap_headers_output_filter()");
 
     /* do the fixup */
-    do_headers_fixup(f->r, hdr_out, serverconf->fixup_out);
-    do_headers_fixup(f->r, hdr_out, dirconf->fixup_out);
+    do_headers_fixup(f->r, f->r->err_headers_out, dirconf->fixup_err);
+    do_headers_fixup(f->r, 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 apr_status_t ap_headers_error_filter(ap_filter_t *f,
+                                            apr_bucket_brigade *in)
+{
+    headers_conf *dirconf = ap_get_module_config(f->r->per_dir_config,
+                                                 &headers_module);
+
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, f->r->server,
+                 "headers: ap_headers_error_filter()");
+
+    /* do the fixup */
+    do_headers_fixup(f->r, f->r->err_headers_out, dirconf->fixup_err);
 
     /* remove ourselves from the filter chain */
     ap_remove_output_filter(f);
@@ -524,15 +558,12 @@ static apr_status_t ap_headers_output_filter(ap_filter_t *f,
 
 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 the fixup */
-    if (serverconf->fixup_in->nelts || dirconf->fixup_in->nelts) {
-        do_headers_fixup(r, hdr_in, serverconf->fixup_in);
-        do_headers_fixup(r, hdr_in, dirconf->fixup_in);
+    if (dirconf->fixup_in->nelts) {
+        do_headers_fixup(r, r->headers_in, dirconf->fixup_in);
     }
 
     return DECLINED;
@@ -540,9 +571,10 @@ static apr_status_t ap_headers_fixup(request_rec *r)
                                         
 static const command_rec headers_cmds[] =
 {
-    AP_INIT_RAW_ARGS("Header", header_cmd, (void *)hdr_out, OR_FILEINFO,
-                   "an action, header and value followed by optional env clause"),
-    AP_INIT_RAW_ARGS("RequestHeader", header_cmd, (void *)hdr_in, OR_FILEINFO,
+    AP_INIT_RAW_ARGS("Header", header_cmd, &hdr_out, OR_FILEINFO,
+                   "an optional condition, an action, header and value "
+                   "followed by optional env clause"),
+    AP_INIT_RAW_ARGS("RequestHeader", header_cmd, &hdr_in, OR_FILEINFO,
                    "an action, header and value"),
     {NULL}
 };
@@ -567,18 +599,21 @@ static void register_hooks(apr_pool_t *p)
 {
     ap_hook_pre_config(header_pre_config,NULL,NULL,APR_HOOK_MIDDLE);
     ap_hook_insert_filter(ap_headers_insert_output_filter, NULL, NULL, APR_HOOK_LAST);
+    ap_hook_insert_error_filter(ap_headers_insert_error_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,
                               NULL, AP_FTYPE_CONTENT_SET);
+    ap_register_output_filter("FIXUP_HEADERS_ERR", ap_headers_error_filter,
+                              NULL, AP_FTYPE_CONTENT_SET);
 }
 
 module AP_MODULE_DECLARE_DATA headers_module =
 {
     STANDARD20_MODULE_STUFF,
-    create_headers_dir_config,  /* dir config creater */
+    create_headers_config,      /* dir config creater */
     merge_headers_config,       /* dir merger --- default is to override */
-    create_headers_config,      /* server config */
-    merge_headers_config,       /* merge server configs */
+    NULL,                       /* server config */
+    NULL,                       /* merge server configs */
     headers_cmds,               /* command apr_table_t */
-    register_hooks             /* register hooks */
+    register_hooks              /* register hooks */
 };