summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGraham Leggett <minfrin@apache.org>2010-11-20 22:39:23 +0100
committerGraham Leggett <minfrin@apache.org>2010-11-20 22:39:23 +0100
commit476bd51775c8663a8b2e06d280d655ab7987e8a6 (patch)
tree84a693a582ac513c3cc3c3c482e2393e3e886c59
parentUpdate status of ap_expr and Limit (diff)
downloadapache2-476bd51775c8663a8b2e06d280d655ab7987e8a6.tar.xz
apache2-476bd51775c8663a8b2e06d280d655ab7987e8a6.zip
mod_include: Add the onerror attribute to the include element, allowing
an URL to be specified to include on error. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1037335 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--CHANGES4
-rw-r--r--docs/manual/mod/mod_include.xml31
-rw-r--r--docs/manual/new_features_2_4.xml7
-rw-r--r--modules/filters/mod_include.c37
4 files changed, 66 insertions, 13 deletions
diff --git a/CHANGES b/CHANGES
index 1c736e6c2c..23cc717545 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,10 @@ Changes with Apache 2.3.9
Fix a denial of service attack against mod_reqtimeout.
[Stefan Fritsch]
+ *) mod_include: Add the onerror attribute to the include element,
+ allowing an URL to be specified to include on error. [Graham
+ Leggett]
+
*) mod_cache_disk: mod_disk_cache renamed to mod_cache_disk, to be
consistent with the naming of other modules. [Graham Leggett]
diff --git a/docs/manual/mod/mod_include.xml b/docs/manual/mod/mod_include.xml
index 9c479f4460..f843718a77 100644
--- a/docs/manual/mod/mod_include.xml
+++ b/docs/manual/mod/mod_include.xml
@@ -331,9 +331,10 @@
scripts are invoked as normal using the complete URL given in
the command, including any query string.</p>
- <p>An attribute defines the location of the document; the
- inclusion is done for each attribute given to the include
- command. The valid attributes are:</p>
+ <p>An attribute defines the location of the document, and may
+ appear more than once in an include element; an inclusion is
+ done for each attribute given to the include command in turn.
+ The valid attributes are:</p>
<dl>
<dt><code>file</code></dt>
@@ -359,11 +360,11 @@
<p>If the specified URL is a CGI program, the program will be
executed and its output inserted in place of the directive in the
parsed file. You may include a query string in a CGI url:</p>
-
+
<example>
&lt;!--#include virtual="/cgi-bin/example.cgi?argument=value" --&gt;
</example>
-
+
<p><code>include virtual</code> should be used in preference
to <code>exec cgi</code> to include the output of CGI programs
into an HTML document.</p>
@@ -376,6 +377,26 @@
requests.</p>
</dd>
+
+ <dt><code>onerror</code></dt>
+ <dd><p>The value is a (%-encoded) URL-path which is shown should a
+ previous attempt to include a file or virtual attribute failed.
+ To be effective, this attribute must be specified after the
+ file or virtual attributes being covered. If the attempt to
+ include the onerror path fails, or if onerror is not specified, the
+ default error message will be included.</p>
+
+ <example>
+ # Simple example<br />
+ &lt;!--#include virtual="/not-exist.html" onerror="/error.html" --&gt;
+ </example>
+
+ <example>
+ # Dedicated onerror paths<br />
+ &lt;!--#include virtual="/path-a.html" onerror="/error-a.html" virtual="/path-b.html" onerror="/error-b.html" --&gt;
+ </example>
+
+ </dd>
</dl>
</section> <!-- /include -->
diff --git a/docs/manual/new_features_2_4.xml b/docs/manual/new_features_2_4.xml
index b4a9aa74b6..94539bd5d9 100644
--- a/docs/manual/new_features_2_4.xml
+++ b/docs/manual/new_features_2_4.xml
@@ -107,6 +107,13 @@
<dt><module>mod_allowmethods</module></dt>
<dd>New module to restrict certain HTTP methods without interfering with
authentication or authorization.</dd>
+
+ <dt><module>mod_include</module></dt>
+
+ <dd>Support for the 'onerror' attribute within an 'include' element,
+ allowing an error document to be served on error instead of the default
+ error string.</dd>
+
</dl>
</section>
diff --git a/modules/filters/mod_include.c b/modules/filters/mod_include.c
index 45ea141116..c8d90fd055 100644
--- a/modules/filters/mod_include.c
+++ b/modules/filters/mod_include.c
@@ -1648,12 +1648,19 @@ static int find_file(request_rec *r, const char *directive, const char *tag,
}
/*
- * <!--#include virtual|file="..." [virtual|file="..."] ... -->
+ * <!--#include virtual|file="..." [onerror|virtual|file="..."] ... -->
+ *
+ * Output each file/virtual in turn until one of them returns an error.
+ * On error, ignore all further file/virtual attributes until we reach
+ * an onerror attribute, where we make an attempt to serve the onerror
+ * virtual url. If onerror fails, or no onerror is present, the default
+ * error string is inserted into the stream.
*/
static apr_status_t handle_include(include_ctx_t *ctx, ap_filter_t *f,
apr_bucket_brigade *bb)
{
request_rec *r = f->r;
+ char *last_error;
if (!ctx->argc) {
ap_log_rerror(APLOG_MARK,
@@ -1672,6 +1679,7 @@ static apr_status_t handle_include(include_ctx_t *ctx, ap_filter_t *f,
return APR_SUCCESS;
}
+ last_error = NULL;
while (1) {
char *tag = NULL;
char *tag_val = NULL;
@@ -1684,7 +1692,8 @@ static apr_status_t handle_include(include_ctx_t *ctx, ap_filter_t *f,
break;
}
- if (strcmp(tag, "virtual") && strcmp(tag, "file")) {
+ if (strcmp(tag, "virtual") && strcmp(tag, "file") && strcmp(tag,
+ "onerror")) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "unknown parameter "
"\"%s\" to tag include in %s", tag, r->filename);
SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
@@ -1709,7 +1718,8 @@ static apr_status_t handle_include(include_ctx_t *ctx, ap_filter_t *f,
rr = ap_sub_req_lookup_file(newpath, r, f->next);
}
}
- else {
+ else if ((tag[0] == 'v' && !last_error)
+ || (tag[0] == 'o' && last_error)) {
if (r->kept_body) {
rr = ap_sub_req_method_uri(r->method, parsed_string, r, f->next);
}
@@ -1717,6 +1727,9 @@ static apr_status_t handle_include(include_ctx_t *ctx, ap_filter_t *f,
rr = ap_sub_req_lookup_uri(parsed_string, r, f->next);
}
}
+ else {
+ continue;
+ }
if (!error_fmt && rr->status != HTTP_OK) {
error_fmt = "unable to include \"%s\" in parsed file %s";
@@ -1743,8 +1756,15 @@ static apr_status_t handle_include(include_ctx_t *ctx, ap_filter_t *f,
if (error_fmt) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error_fmt, tag_val,
- r->filename);
- SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
+ r->filename);
+ if (last_error) {
+ /* onerror threw an error, give up completely */
+ break;
+ }
+ last_error = error_fmt;
+ }
+ else {
+ last_error = NULL;
}
/* Do *not* destroy the subrequest here; it may have allocated
@@ -1752,9 +1772,10 @@ static apr_status_t handle_include(include_ctx_t *ctx, ap_filter_t *f,
* r->pool, so that pool must survive as long as this request.
* Yes, this is a memory leak. */
- if (error_fmt) {
- break;
- }
+ }
+
+ if (last_error) {
+ SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
}
return APR_SUCCESS;