summaryrefslogtreecommitdiffstats
path: root/docs/manual/mod/mod_headers.xml
diff options
context:
space:
mode:
authorEric Covener <covener@apache.org>2020-02-06 00:05:44 +0100
committerEric Covener <covener@apache.org>2020-02-06 00:05:44 +0100
commit584b83f2aa2c429d6c815f67e1f03d601de53560 (patch)
tree92b982f3ecb04d3a971e3fc31ebc58fc72dc4883 /docs/manual/mod/mod_headers.xml
parentfr doc rebuild. (diff)
downloadapache2-584b83f2aa2c429d6c815f67e1f03d601de53560.tar.xz
apache2-584b83f2aa2c429d6c815f67e1f03d601de53560.zip
rework the mysteries of onsuccess and always
I thought I was well-versed in this topic but reading my own text and r1844401 while playing with samesite recipes made me want to rewrite it. Pushed the advice down into the actions. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1873675 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
-rw-r--r--docs/manual/mod/mod_headers.xml126
1 files changed, 58 insertions, 68 deletions
diff --git a/docs/manual/mod/mod_headers.xml b/docs/manual/mod/mod_headers.xml
index e14a632c1a..e2f9748e22 100644
--- a/docs/manual/mod/mod_headers.xml
+++ b/docs/manual/mod/mod_headers.xml
@@ -330,68 +330,16 @@ available in 2.4.10 and later</compatibility>
<p> The optional <var>condition</var> argument determines which internal
table of responses headers this directive will operate against:
<code>onsuccess</code> (default, can be omitted) or <code>always</code>.
- The difference between the two lists is that the headers contained in the
- latter are added to the response even on error, and persisted across
- internal redirects (for example, ErrorDocument handlers).
-
- Note also that repeating this directive with both conditions makes sense in
- some scenarios because <code>always</code> is not a superset of
- <code>onsuccess</code> with respect to existing headers:</p>
-
- <ul>
- <li> You're adding a header to a locally generated non-success (non-2xx) response, such
- as a redirect, in which case only the table corresponding to
- <code>always</code> is used in the ultimate response.</li>
- <li> You're modifying or removing a header generated by a CGI script
- or by <module>mod_proxy_fcgi</module>,
- in which case the CGI scripts' headers are in the table corresponding to
- <code>always</code> and not in the default table.</li>
- <li> You're modifying or removing a header generated by some piece of
- the server but that header is not being found by the default
- <code>onsuccess</code> condition.</li>
- </ul>
-
- <p>This difference between <code>onsuccess</code> and <code>always</code> is
- a feature that resulted as a consequence of how httpd internally stores
- headers for a HTTP response, since it does not offer any "normalized" single
- list of headers. The main problem that can arise if the following concept
- is not kept in mind while writing the configuration is that some HTTP responses
- might end up with the same header duplicated (confusing users or sometimes even
- HTTP clients). For example, suppose that you have a simple PHP proxy setup with
- <module>mod_proxy_fcgi</module> and your backend PHP scripts adds the
- <code>X-Foo: bar</code> header to each HTTP response. As described above,
- <module>mod_proxy_fcgi</module> uses the <code>always</code> table to store
- headers, so a configuration like the following ends up in the wrong result, namely
- having the header duplicated with both values:</p>
-
- <highlight language="config">
-# X-Foo's value is set in the 'onsuccess' headers table
-Header set X-Foo: baz
- </highlight>
-
- <p>To circumvent this limitation, there are some known configuration
- patterns that can help, like the following:</p>
-
- <highlight language="config">
-# 'onsuccess' can be omitted since it is the default
-Header onsuccess unset X-Foo
-Header always set X-Foo "baz"
- </highlight>
-
- <p>Separately from the <var>condition</var> parameter described above, you
- can limit an action based on HTTP status codes for e.g. proxied or CGI
- requests. See the example that uses %{REQUEST_STATUS} in the section above.</p>
-
- <p>The action it performs is determined by the first
- argument (second argument if a <var>condition</var> is specified).
- This can be one of the following values:</p>
+ Guidance on when to specify <code>always</code> is provided relative to each
+ action below. </p>
<note type="warning"><title>Warning</title>
- <p>Please read the difference between <code>always</code>
- and <code>onsuccess</code> headers list described above
- before start reading the actions list, since that important
- concept still applies. Each action, in fact, works as described
- but only on the target headers list.</p>
+ <p>Carefully read the difference between <code>always</code>
+ and <code>onsuccess</code> for each action listed below as the
+ behavior can be unintuitive and is a frequent source of confusion.
+ Where the guidance suggest repeating the conditions, it is safe to try
+ each experimentally and use the one you find effective to match the
+ pre-existing header.</p>
</note>
<dl>
@@ -400,19 +348,30 @@ Header always set X-Foo "baz"
even if this header already exists. This can result in two
(or more) headers having the same name. This can lead to
unforeseen consequences, and in general <code>set</code>,
- <code>append</code> or <code>merge</code> should be used instead.</dd>
+ <code>append</code> or <code>merge</code> should be used instead.
+ <p>Specify a condition of <code>always</code> if you want the header to
+ be included in non-2xx response (such as redirects or errors)</p>
+ </dd>
<dt><code>append</code></dt>
<dd>The response header is appended to any existing header of
the same name. When a new value is merged onto an existing
header it is separated from the existing header with a comma.
- This is the HTTP standard way of giving a header multiple values.</dd>
+ This is the HTTP standard way of giving a header multiple values.
+ <p>If the header was added by this module, you must match the condition
+ parameter that was originally used. Otherwise, you must determine by trial
+ and error whether <code>always</code> should be specified because you can't
+ reliably know which internal table the existing value is present in.</p>
+ </dd>
<dt><code>echo</code></dt>
<dd>Request headers with this name are echoed back in the
response headers. <var>header</var> may be a
<glossary ref="regex">regular expression</glossary>.
- <var>value</var> must be omitted.</dd>
+ <var>value</var> must be omitted.
+ <p>Specify a condition of <code>always</code> if you want the header to
+ be included in non-2xx response (such as redirects or errors).</p>
+ </dd>
<dt><code>edit</code></dt>
<dt><code>edit*</code></dt>
@@ -424,7 +383,11 @@ Header always set X-Foo "baz"
The <code>edit</code> form will match and replace exactly once
in a header value, whereas the <code>edit*</code> form will replace
<em>every</em> instance of the search pattern if it appears more
- than once.</dd>
+ than once.
+ <p>Because you cannot reliably know which internal header table might have a match,
+ you should repeat your edit/edit* directive with both <code>always</code> and
+ <code>onsuccess</code>.</p>
+ </dd>
<dt><code>merge</code></dt>
<dd>The response header is appended to any existing header of
@@ -434,15 +397,32 @@ Header always set X-Foo "baz"
This is the HTTP standard way of giving a header multiple values.
Values are compared in a case sensitive manner, and after
all format specifiers have been processed. Values in double quotes
- are considered different from otherwise identical unquoted values.</dd>
+ are considered different from otherwise identical unquoted values.
+ <p>If the header was added by this module, you must match the condition
+ parameter that was originally used. Otherwise, you must determine by trial
+ and error whether <code>always</code> should be specified because you can't
+ reliably know which internal table the existing value is present in.</p>
+ </dd>
+
<dt><code>set</code></dt>
<dd>The response header is set, replacing any previous header
- with this name. The <var>value</var> may be a format string.</dd>
+ with this name. The <var>value</var> may be a format string.
+ <p>If the header was added by this module, you must match the condition
+ parameter that was originally used. Otherwise, you must determine by trial
+ and error whether <code>always</code> should be specified because you can't
+ reliably know which internal table the existing value is present in.</p>
+ </dd>
+
<dt><code>setifempty</code></dt>
<dd>The request header is set, but only if there is no previous header
with this name.
+ <p>If the header was added by this module, you must match the condition
+ parameter that was originally used. Otherwise, you must determine by trial
+ and error whether <code>always</code> should be specified because you can't
+ reliably know which internal table the existing value is present in.</p>
+
<note>
The Content-Type header is a special use case since there might be
the chance that its value have been determined but the header is not part
@@ -454,17 +434,27 @@ Header always set X-Foo "baz"
</highlight>
</note></dd>
+
<dt><code>unset</code></dt>
<dd>The response header of this name is removed, if it exists.
If there are multiple headers of the same name, all will be
- removed. <var>value</var> must be omitted.</dd>
+ removed. <var>value</var> must be omitted.
+ <p>Because you cannot reliably know which internal header table might have a match,
+ you should repeat your this directive with both <code>always</code> and
+ <code>onsuccess</code>.</p>
+ </dd>
<dt><code>note</code></dt>
<dd>The value of the named response <var>header</var> is copied into an
internal note whose name is given by <var>value</var>. This is useful
if a header sent by a CGI or proxied resource is configured to be unset
but should also be logged.<br />
- Available in 2.4.7 and later.</dd>
+ Available in 2.4.7 and later.
+ <p>If the header was added by this module, you must match the condition
+ parameter that was originally used. Otherwise, you must determine by trial
+ and error whether <code>always</code> should be specified because you can't
+ reliably know which internal table the existing value is present in.</p>
+ </dd>
</dl>