Changes with Apache 2.3.2
[ When backported to 2.2.x, remove entry from this file ]
+ *) mod_ext_filter: We need to detect failure to startup the filter
+ program (a mangled response is not acceptable). Fix to detect
+ failure, and offer configuration option either to abort or
+ to remove the filter and continue.
+ PR 41120 [Nick Kew]
+
*) mod_session_crypto: Rewrite the session_crypto module against the
apr_crypto API. [Graham Leggett]
messages written to standard error by the external filter
program will be saved in the Apache error log.
<code>NoLogStderr</code> disables this feature.</dd>
+
+ <dt><code>Onfail=[abort|remove]</code></dt>
+ <dd>Determines how to proceed if the external filter program
+ cannot be started. With <code>abort</code> (the default value)
+ the request will be aborted. With <code>remove</code>, the
+ filter is removed and the request continues without it.</dd>
</dl>
<example><title>Example</title>
typedef struct ef_dir_t {
int debug;
int log_stderr;
+ int onfail;
} ef_dir_t;
typedef struct ef_ctx_t {
apr_off_t);
#define DBGLVL_SHOWOPTIONS 1
-#define DBGLVL_ERRORCHECK 2
#define DBGLVL_GORY 9
#define ERRFN_USERDATA_KEY "EXTFILTCHILDERRFN"
dc->debug = -1;
dc->log_stderr = -1;
+ dc->onfail = -1;
return dc;
}
a->log_stderr = base->log_stderr;
}
+ if (over->onfail != -1) { /* if admin coded something... */
+ a->onfail = over->onfail;
+ }
+ else {
+ a->onfail = base->onfail;
+ }
+
return a;
}
else if (!strcasecmp(arg, "NoLogStderr")) {
dc->log_stderr = 0;
}
+ else if (!strcasecmp(arg, "Onfail=remove")) {
+ dc->onfail = 1;
+ }
+ else if (!strcasecmp(arg, "Onfail=abort")) {
+ dc->onfail = 0;
+ }
else {
return apr_pstrcat(cmd->temp_pool,
"Invalid ExtFilterOptions option: ",
ap_assert(rc == APR_SUCCESS);
apr_pool_userdata_set(f->r, ERRFN_USERDATA_KEY, apr_pool_cleanup_null, ctx->p);
- if (dc->debug >= DBGLVL_ERRORCHECK) {
- rc = apr_procattr_error_check_set(ctx->procattr, 1);
- ap_assert(rc == APR_SUCCESS);
+ rc = apr_procattr_error_check_set(ctx->procattr, 1);
+ if (rc != APR_SUCCESS) {
+ return rc;
}
/* add standard CGI variables as well as DOCUMENT_URI, DOCUMENT_PATH_INFO,
if (!ctx) {
if ((rv = init_filter_instance(f)) != APR_SUCCESS) {
- return rv;
+ ctx = f->ctx;
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "can't initialise output filter %s: %s",
+ f->frec->name,
+ ctx->dc->onfail ? "removing" : "aborting");
+ ap_remove_output_filter(f);
+ if (ctx->dc->onfail) {
+ return ap_pass_brigade(f->next, bb);
+ }
+ else {
+ f->r->status = HTTP_INTERNAL_SERVER_ERROR;
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
}
ctx = f->ctx;
}
if (!ctx) {
if ((rv = init_filter_instance(f)) != APR_SUCCESS) {
- return rv;
+ ctx = f->ctx;
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
+ "can't initialise input filter %s: %s",
+ f->frec->name,
+ ctx->dc->onfail ? "removing" : "aborting");
+ ap_remove_input_filter(f);
+ if (ctx->dc->onfail) {
+ return ap_get_brigade(f->next, bb, mode, block, readbytes);
+ }
+ else {
+ f->r->status = HTTP_INTERNAL_SERVER_ERROR;
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
}
ctx = f->ctx;
}