Skip to content

Commit 0010915

Browse files
author
Andre Malo
committed
Fix regression from 1.3:
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
1 parent 51cad98 commit 0010915

5 files changed

Lines changed: 112 additions & 57 deletions

File tree

CHANGES

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
Changes with Apache 2.0.51
22

3+
*) Backport from 2.1 / Regression from 1.3: mod_headers now knows
4+
again the functionality of the ErrorHeader directive. But instead
5+
using this misnomer additional flags to the Header directive were
6+
introduced ("always" and "onsuccess", defaulting to the latter).
7+
PR 28657. [Andr� Malo]
8+
39
*) Use the higher performing 'httpready' Accept Filter on all platforms
410
except FreeBSD < 4.1.1. [Paul Querna]
511

STATUS

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
APACHE 2.0 STATUS: -*-text-*-
2-
Last modified at [$Date: 2004/08/19 18:55:47 $]
2+
Last modified at [$Date: 2004/08/19 22:53:12 $]
33

44
Release:
55

@@ -213,13 +213,6 @@ PATCHES TO BACKPORT FROM 2.1
213213
server/config.c: r1.175
214214
+1: nd
215215

216-
*) mod_headers: Regression from 1.3: There's no ErrorHeader directive.
217-
Since this was always a misnomer, it was dropped in 2.1 and
218-
Header was extended instead. Backport this from 2.1 and document
219-
this in the upgrading docs. A 2.0 patch is here:
220-
http://www.apache.org/~nd/header_always_2.0.diff
221-
+1: nd, bnicholes, jorton
222-
223216
*) mod_rewrite: Fix confused map cache (with maps in different VHs using
224217
the same name). PR 26462. (2.0 + 1.3)
225218
A patch for 1.3 is here (2.0 goes similar):

docs/manual/mod/mod_headers.xml

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0"?>
22
<!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">
33
<?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
4-
<!-- $Revision: 1.5.2.5 $ -->
4+
<!-- $Revision: 1.5.2.6 $ -->
55

66
<!--
77
Copyright 2002-2004 The Apache Software Foundation
@@ -194,17 +194,28 @@ is available only in Apache 2.0</compatibility>
194194
<directivesynopsis>
195195
<name>Header</name>
196196
<description>Configure HTTP response headers</description>
197-
<syntax>Header set|append|add|unset|echo <var>header</var>
198-
[<var>value</var> [env=[!]<var>variable</var>]]</syntax>
197+
<syntax>Header [<var>condition</var>] set|append|add|unset|echo
198+
<var>header</var> [<var>value</var>] [env=[!]<var>variable</var>]</syntax>
199199
<contextlist><context>server config</context><context>virtual host</context>
200200
<context>directory</context><context>.htaccess</context></contextlist>
201201
<override>FileInfo</override>
202+
<compatibility><var>Condition</var> is available in version 2.0.51 and
203+
later</compatibility>
202204

203205
<usage>
204206
<p>This directive can replace, merge or remove HTTP response
205207
headers. The header is modified just after the content handler
206208
and output filters are run, allowing outgoing headers to be
207-
modified. The action it performs is determined by the first
209+
modified.</p>
210+
211+
<p>The optional <var>condition</var> can be either <code>onsuccess</code>
212+
or <code>always</code>. It determines, which internal header table should be
213+
operated on. <code>onsuccess</code> stands for <code>2<var>xx</var></code>
214+
status codes and <code>always</code> for all status codes (including
215+
<code>2<var>xx</var></code>). Especially if you want to unset headers
216+
set by certain modules, you should try out, which table is affected.</p>
217+
218+
<p>The action it performs is determined by the second
208219
argument. This can be one of the following values:</p>
209220

210221
<dl>

docs/manual/upgrading.xml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version='1.0' encoding='UTF-8' ?>
22
<!DOCTYPE manualpage SYSTEM "./style/manualpage.dtd">
33
<?xml-stylesheet type="text/xsl" href="./style/manual.en.xsl"?>
4-
<!-- $Revision: 1.6.2.8 $ -->
4+
<!-- $Revision: 1.6.2.9 $ -->
55

66
<!--
77
Copyright 2002-2004 The Apache Software Foundation
@@ -169,6 +169,16 @@ Apache 2.0</a></seealso>
169169
files. The old behavior can be restored using the <directive
170170
module="mod_mime">MultiviewsMatch</directive> directive.</li>
171171

172+
<li>(<em>since version 2.0.51</em>)
173+
<p>The functionality of the <code>ErrorHeader</code> directive was
174+
put together with the <directive module="mod_headers">Header</directive>
175+
directive, since it was a misnomer. Use</p>
176+
177+
<example>
178+
Header always set foo bar
179+
</example>
180+
181+
<p>instead to get the desired bahviour.</p></li>
172182
</ul>
173183
</section>
174184

modules/metadata/mod_headers.c

Lines changed: 79 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
#include "http_request.h"
7777
#include "http_log.h"
7878
#include "util_filter.h"
79+
#include "http_protocol.h" /* ap_hook_insert_error_filter */
7980

8081
/* format_tag_hash is initialized during pre-config */
8182
static apr_hash_t *format_tag_hash;
@@ -88,10 +89,12 @@ typedef enum {
8889
hdr_echo = 'e' /* echo headers from request to response */
8990
} hdr_actions;
9091

91-
typedef enum {
92-
hdr_in = 0, /* RequestHeader */
93-
hdr_out = 1 /* Header */
94-
} hdr_inout;
92+
/*
93+
* magic cmd->info values
94+
*/
95+
static char hdr_in = '0'; /* RequestHeader */
96+
static char hdr_out = '1'; /* Header onsuccess */
97+
static char hdr_err = '2'; /* Header always */
9598

9699
/*
97100
* There is an array of struct format_tag per Header/RequestHeader
@@ -126,6 +129,7 @@ typedef struct {
126129
typedef struct {
127130
apr_array_header_t *fixup_in;
128131
apr_array_header_t *fixup_out;
132+
apr_array_header_t *fixup_err;
129133
} headers_conf;
130134

131135
module AP_MODULE_DECLARE_DATA headers_module;
@@ -158,29 +162,26 @@ static const char *header_request_env_var(request_rec *r, char *a)
158162
/*
159163
* Config routines
160164
*/
161-
static void *create_headers_config(apr_pool_t *p, server_rec *s)
165+
static void *create_headers_config(apr_pool_t *p, char *dummy)
162166
{
163-
headers_conf *conf = apr_pcalloc(p, sizeof(*conf));
167+
headers_conf *conf = apr_palloc(p, sizeof(*conf));
164168

165169
conf->fixup_in = apr_array_make(p, 2, sizeof(header_entry));
166170
conf->fixup_out = apr_array_make(p, 2, sizeof(header_entry));
171+
conf->fixup_err = apr_array_make(p, 2, sizeof(header_entry));
167172

168173
return conf;
169174
}
170175

171-
static void *create_headers_dir_config(apr_pool_t *p, char *d)
172-
{
173-
return create_headers_config(p, NULL);
174-
}
175-
176176
static void *merge_headers_config(apr_pool_t *p, void *basev, void *overridesv)
177177
{
178-
headers_conf *newconf = apr_pcalloc(p, sizeof(*newconf));
178+
headers_conf *newconf = apr_palloc(p, sizeof(*newconf));
179179
headers_conf *base = basev;
180180
headers_conf *overrides = overridesv;
181181

182182
newconf->fixup_in = apr_array_append(p, base->fixup_in, overrides->fixup_in);
183183
newconf->fixup_out = apr_array_append(p, base->fixup_out, overrides->fixup_out);
184+
newconf->fixup_err = apr_array_append(p, base->fixup_err, overrides->fixup_err);
184185

185186
return newconf;
186187
}
@@ -317,17 +318,12 @@ static const char *header_inout_cmd(cmd_parms *cmd, void *indirconf,
317318
char *colon;
318319
char *hdr = apr_pstrdup(cmd->pool, inhdr);
319320
header_entry *new;
320-
server_rec *s = cmd->server;
321-
headers_conf *serverconf = ap_get_module_config(s->module_config,
322-
&headers_module);
323-
hdr_inout inout = (hdr_inout)cmd->info;
321+
apr_array_header_t *fixup = (cmd->info == &hdr_in)
322+
? dirconf->fixup_in : (cmd->info == &hdr_err)
323+
? dirconf->fixup_err
324+
: dirconf->fixup_out;
324325

325-
if (cmd->path) {
326-
new = (header_entry *) apr_array_push((hdr_in == inout) ? dirconf->fixup_in : dirconf->fixup_out);
327-
}
328-
else {
329-
new = (header_entry *) apr_array_push((hdr_in == inout) ? serverconf->fixup_in : serverconf->fixup_out);
330-
}
326+
new = (header_entry *) apr_array_push(fixup);
331327

332328
if (!strcasecmp(action, "set"))
333329
new->action = hdr_set;
@@ -350,7 +346,7 @@ static const char *header_inout_cmd(cmd_parms *cmd, void *indirconf,
350346
regex_t *regex;
351347
if (value)
352348
return "Header echo takes two arguments";
353-
else if (inout != hdr_out)
349+
else if (cmd->info == &hdr_in)
354350
return "Header echo only valid on Header directive";
355351
else {
356352
regex = ap_pregcomp(cmd->pool, hdr, REG_EXTENDED | REG_NOSUB);
@@ -396,10 +392,24 @@ static const char *header_cmd(cmd_parms *cmd, void *indirconf,
396392

397393
s = apr_pstrdup(cmd->pool, args);
398394
action = ap_getword_conf(cmd->pool, &s);
395+
if (cmd->info == &hdr_out) {
396+
if (!strcasecmp(action, "always")) {
397+
cmd->info = &hdr_err;
398+
action = ap_getword_conf(cmd->pool, &s);
399+
}
400+
else if (!strcasecmp(action, "onsuccess")) {
401+
action = ap_getword_conf(cmd->pool, &s);
402+
}
403+
}
399404
hdr = ap_getword_conf(cmd->pool, &s);
400405
val = *s ? ap_getword_conf(cmd->pool, &s) : NULL;
401406
envclause = *s ? ap_getword_conf(cmd->pool, &s) : NULL;
402407

408+
if (*s) {
409+
return apr_pstrcat(cmd->pool, cmd->cmd->name,
410+
" has too many arguments", NULL);
411+
}
412+
403413
return header_inout_cmd(cmd, indirconf, action, hdr, val, envclause);
404414
}
405415

@@ -440,11 +450,10 @@ static int echo_header(echo_do *v, const char *key, const char *val)
440450
return 1;
441451
}
442452

443-
static void do_headers_fixup(request_rec *r, hdr_inout inout,
453+
static void do_headers_fixup(request_rec *r, apr_table_t *headers,
444454
apr_array_header_t *fixup)
445455
{
446456
int i;
447-
apr_table_t *headers = (hdr_in == inout) ? r->headers_in : r->headers_out;
448457

449458
for (i = 0; i < fixup->nelts; ++i) {
450459
header_entry *hdr = &((header_entry *) (fixup->elts))[i];
@@ -490,30 +499,55 @@ static void do_headers_fixup(request_rec *r, hdr_inout inout,
490499

491500
static void ap_headers_insert_output_filter(request_rec *r)
492501
{
493-
headers_conf *serverconf = ap_get_module_config(r->server->module_config,
494-
&headers_module);
495502
headers_conf *dirconf = ap_get_module_config(r->per_dir_config,
496503
&headers_module);
497504

498-
if (serverconf->fixup_out->nelts || dirconf->fixup_out->nelts) {
505+
if (dirconf->fixup_out->nelts || dirconf->fixup_err->nelts) {
499506
ap_add_output_filter("FIXUP_HEADERS_OUT", NULL, r, r->connection);
500507
}
501508
}
502509

510+
static void ap_headers_insert_error_filter(request_rec *r)
511+
{
512+
headers_conf *dirconf = ap_get_module_config(r->per_dir_config,
513+
&headers_module);
514+
515+
if (dirconf->fixup_err->nelts) {
516+
ap_add_output_filter("FIXUP_HEADERS_ERR", NULL, r, r->connection);
517+
}
518+
}
519+
503520
static apr_status_t ap_headers_output_filter(ap_filter_t *f,
504521
apr_bucket_brigade *in)
505522
{
506-
headers_conf *serverconf = ap_get_module_config(f->r->server->module_config,
507-
&headers_module);
508523
headers_conf *dirconf = ap_get_module_config(f->r->per_dir_config,
509524
&headers_module);
510525

511526
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, f->r->server,
512527
"headers: ap_headers_output_filter()");
513528

514529
/* do the fixup */
515-
do_headers_fixup(f->r, hdr_out, serverconf->fixup_out);
516-
do_headers_fixup(f->r, hdr_out, dirconf->fixup_out);
530+
do_headers_fixup(f->r, f->r->err_headers_out, dirconf->fixup_err);
531+
do_headers_fixup(f->r, f->r->headers_out, dirconf->fixup_out);
532+
533+
/* remove ourselves from the filter chain */
534+
ap_remove_output_filter(f);
535+
536+
/* send the data up the stack */
537+
return ap_pass_brigade(f->next,in);
538+
}
539+
540+
static apr_status_t ap_headers_error_filter(ap_filter_t *f,
541+
apr_bucket_brigade *in)
542+
{
543+
headers_conf *dirconf = ap_get_module_config(f->r->per_dir_config,
544+
&headers_module);
545+
546+
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, f->r->server,
547+
"headers: ap_headers_error_filter()");
548+
549+
/* do the fixup */
550+
do_headers_fixup(f->r, f->r->err_headers_out, dirconf->fixup_err);
517551

518552
/* remove ourselves from the filter chain */
519553
ap_remove_output_filter(f);
@@ -524,25 +558,23 @@ static apr_status_t ap_headers_output_filter(ap_filter_t *f,
524558

525559
static apr_status_t ap_headers_fixup(request_rec *r)
526560
{
527-
headers_conf *serverconf = ap_get_module_config(r->server->module_config,
528-
&headers_module);
529561
headers_conf *dirconf = ap_get_module_config(r->per_dir_config,
530562
&headers_module);
531563

532564
/* do the fixup */
533-
if (serverconf->fixup_in->nelts || dirconf->fixup_in->nelts) {
534-
do_headers_fixup(r, hdr_in, serverconf->fixup_in);
535-
do_headers_fixup(r, hdr_in, dirconf->fixup_in);
565+
if (dirconf->fixup_in->nelts) {
566+
do_headers_fixup(r, r->headers_in, dirconf->fixup_in);
536567
}
537568

538569
return DECLINED;
539570
}
540571

541572
static const command_rec headers_cmds[] =
542573
{
543-
AP_INIT_RAW_ARGS("Header", header_cmd, (void *)hdr_out, OR_FILEINFO,
544-
"an action, header and value followed by optional env clause"),
545-
AP_INIT_RAW_ARGS("RequestHeader", header_cmd, (void *)hdr_in, OR_FILEINFO,
574+
AP_INIT_RAW_ARGS("Header", header_cmd, &hdr_out, OR_FILEINFO,
575+
"an optional condition, an action, header and value "
576+
"followed by optional env clause"),
577+
AP_INIT_RAW_ARGS("RequestHeader", header_cmd, &hdr_in, OR_FILEINFO,
546578
"an action, header and value"),
547579
{NULL}
548580
};
@@ -567,18 +599,21 @@ static void register_hooks(apr_pool_t *p)
567599
{
568600
ap_hook_pre_config(header_pre_config,NULL,NULL,APR_HOOK_MIDDLE);
569601
ap_hook_insert_filter(ap_headers_insert_output_filter, NULL, NULL, APR_HOOK_LAST);
602+
ap_hook_insert_error_filter(ap_headers_insert_error_filter, NULL, NULL, APR_HOOK_LAST);
570603
ap_hook_fixups(ap_headers_fixup, NULL, NULL, APR_HOOK_LAST);
571604
ap_register_output_filter("FIXUP_HEADERS_OUT", ap_headers_output_filter,
572605
NULL, AP_FTYPE_CONTENT_SET);
606+
ap_register_output_filter("FIXUP_HEADERS_ERR", ap_headers_error_filter,
607+
NULL, AP_FTYPE_CONTENT_SET);
573608
}
574609

575610
module AP_MODULE_DECLARE_DATA headers_module =
576611
{
577612
STANDARD20_MODULE_STUFF,
578-
create_headers_dir_config, /* dir config creater */
613+
create_headers_config, /* dir config creater */
579614
merge_headers_config, /* dir merger --- default is to override */
580-
create_headers_config, /* server config */
581-
merge_headers_config, /* merge server configs */
615+
NULL, /* server config */
616+
NULL, /* merge server configs */
582617
headers_cmds, /* command apr_table_t */
583-
register_hooks /* register hooks */
618+
register_hooks /* register hooks */
584619
};

0 commit comments

Comments
 (0)