From: Graham Leggett Date: Sat, 20 Nov 2010 21:39:23 +0000 (+0000) Subject: mod_include: Add the onerror attribute to the include element, allowing X-Git-Tag: 2.3.9~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=476bd51775c8663a8b2e06d280d655ab7987e8a6;p=thirdparty%2Fapache%2Fhttpd.git 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 --- diff --git a/CHANGES b/CHANGES index 1c736e6c2c5..23cc7175459 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 9c479f4460e..f843718a772 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.

-

An attribute defines the location of the document; the - inclusion is done for each attribute given to the include - command. The valid attributes are:

+

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:

file
@@ -359,11 +360,11 @@

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:

- + <!--#include virtual="/cgi-bin/example.cgi?argument=value" --> - +

include virtual should be used in preference to exec cgi to include the output of CGI programs into an HTML document.

@@ -375,6 +376,26 @@ Without the directive, all subrequests are processed as GET requests.

+ + +
onerror
+

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.

+ + + # Simple example
+ <!--#include virtual="/not-exist.html" onerror="/error.html" --> +
+ + + # Dedicated onerror paths
+ <!--#include virtual="/path-a.html" onerror="/error-a.html" virtual="/path-b.html" onerror="/error-b.html" --> +
+
diff --git a/docs/manual/new_features_2_4.xml b/docs/manual/new_features_2_4.xml index b4a9aa74b66..94539bd5d9e 100644 --- a/docs/manual/new_features_2_4.xml +++ b/docs/manual/new_features_2_4.xml @@ -107,6 +107,13 @@
mod_allowmethods
New module to restrict certain HTTP methods without interfering with authentication or authorization.
+ +
mod_include
+ +
Support for the 'onerror' attribute within an 'include' element, + allowing an error document to be served on error instead of the default + error string.
+ diff --git a/modules/filters/mod_include.c b/modules/filters/mod_include.c index 45ea141116d..c8d90fd0552 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, } /* - * + * + * + * 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;