Return-Path: Delivered-To: apmail-httpd-dev-archive@httpd.apache.org Received: (qmail 51855 invoked by uid 500); 17 Jun 2002 06:30:10 -0000 Mailing-List: contact dev-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list dev@httpd.apache.org Received: (qmail 51842 invoked from network); 17 Jun 2002 06:30:10 -0000 X-Authentication-Warning: cancer.clove.org: jerenk set sender to jerenkrantz@apache.org using -f Date: Sun, 16 Jun 2002 23:30:18 -0700 From: Justin Erenkrantz To: dev@httpd.apache.org Subject: [REPOST] [PATCH] Implement ap_init_filter_func Message-ID: <20020616233018.B22524@apache.org> Mail-Followup-To: Justin Erenkrantz , dev@httpd.apache.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5i X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N This is a repost in an attempt to close the impasse between myself and Greg on what to do with this patch. Greg has expressed reservations about this approach, and I'm not willing to commit until we obtain consensus. I have expressed concerns with Greg's proposed solutions in reply to my original posting as well. For those who missed the earlier conversation, a rehash is below. I'm trying to rephrase the arguments because it seems that there is a lot of misunderstanding between myself and Greg as to why this patch is needed. Hopefully, this will explain why I think we need this patch and why I believe my solution would work. Q: What problem are we trying to solve? A: Currently, any request to a page that has mod_include'd components and an If-Modified-Since header (or headers for conditional GETs) may improperly return 304 (HTTP_NOT_MODIFIED) causing the client to display old data. Q: Why does it return 304? A: The server determines that the If-Modified-Since date is newer than the modification of the static file backing the mod_include request. Therefore, a 304 status code is returned to the client. Q: Isn't this valid? A: No, it isn't. By definition, requests with mod_include involved should not be eligible for 304-responses. The only way to know what the real modification date of the resource is by walking (parsing) the entire document and determining the component with the most recent modification time. It has been the position since the NCSA-era (I believe) that it is not acceptable performance-wise to pre-parse the data. Therefore, we must take the most conservative action possible - which means disabling 304s. Q: Isn't there an exception? A: Yes, the exception to this case is the XBitHack full directive which indicates that it is okay for 304s and mod_include'd requests only when the execution bit on the file is set. This is a hack. Q: Where is this check for 304 made? A: This check is performed by individual handlers in a function called ap_meets_conditions(). Each handler is responsible for calling it at the appropriate place to see if we can short-cut generating the data. In the case of mod_include, default_handler() is the usual handler serving the content. Some handlers may not honor conditional-GETs and therefore we must let the handlers decide if/when to call this function. Q: What mechanisms are in place to prevent erroneous 304s? A: There is a no_local_copy flag in request_rec which identifies that this resource does not really reside on the file system and must always be regenerated. So, if mod_include were to set this flag before ap_meets_conditions() is called, ap_meets_conditions() would not examine the conditional GET headers. This means that our original problem is solved. Q: Why not disable 304 responses for all requests with resource filters? A: This is highly inefficient. I believe a large percentage of filters are deterministic. For example, the output of mod_bucketeer's filter is completely determined by its input. Therefore, the only condition where mod_bucketeer's output changes is when the underlying file changes. Therefore, a 304 is possible for some filters. However, for filters such as mod_include and mod_php which may reference other files/resources, the conditional GETs must be avoided. Q: Why not run this in the insert_filters hook? A: I believe that this would be highly inefficient as each module would have to verify that its filter is in the chain and then take appropriate action. This essentially becomes an O(n*m) operation where n is the number of filters in the request and m is the number of modules with an insert_filters hook. Q: Why can this not be handled in the filter itself? A: The filter is only called when there is data to be generated. In the case of the invalid 304 being returned, no data is generated and the filter does not have a chance to intercept it. In short, the filter function is called too late to be of any assistance. Q: What is my solution? A: I believe what is required is a way for a module to insert arbitrary code that is executed before the handler is invoked only when the filter is active for this request. Q: Do all filters need to change? A: As indicated in the patch below, most filters (those that are deterministic based on the file) do not need to do anything other than add a NULL parameter to the filter registration function. The rationale for making this part of the filter_rec rather than as a hook is that multiple hooks of the same type per file are not allowed (AIUI), while it is possible to have multiple filters per file. This allows separate init functions for input and output filters (but also the same!). Q: Can't we call this new function when we insert the filter? A: In theory, yes. However, I believe that doing so may cause unnecessary calls to the initialization function. I would prefer to have it only called when we are about ready to generate data. If we called this new function when we added the filter to the chain, we could call it for subrequests that do not generate data. The intention here is to only call it when the handlers are about ready to be invoked. However, this is not a sticking point and I'd be willing to call it whenever it is inserted. There is also a potential problems with the reuse of filters in subrequests. However, I believe where we call it to be an implementation concern, not a design concern. Q: Does this solve any other problems? A: By implementing this for input buckets, it allows removal of the AP_MODE_INIT filter mode and would enable mod_ssl to place code that is run before any data is generated or read. Also, PHP would be able to only initialize its context when it is present in the filter chain. Currently if it is compiled and loaded, PHP will setup its per-request context even if the PHP output filters are not required for this resource. This is inefficient. I would like to have a resolution for this in place for the next release of 2.0 as this requires all filters to be changed. And, I believe we need to come to a consensus on this matter because our current code is broken. I would definitely love to hear other suggestions on how to solve the original problem in an extensible and clean way. After much contemplation, I believe this is the best possible solution I can conceive of. Thanks for reading this! -- justin Index: include/util_filter.h =================================================================== RCS file: /home/cvs/httpd-2.0/include/util_filter.h,v retrieving revision 1.72 diff -u -r1.72 util_filter.h --- include/util_filter.h 8 Jun 2002 03:05:06 -0000 1.72 +++ include/util_filter.h 17 Jun 2002 05:35:06 -0000 @@ -153,12 +153,19 @@ * for setting the association between a name for a filter and its * associated callback (and other information). * + * If the initialization function argument passed to the registration + * functions is non-NULL, it will be called iff the filter is in the input + * or output filter chains and before any data is generated to allow the + * filter to prepare for processing. + * * The *bucket structure (and all those referenced by ->next and ->prev) * should be considered "const". The filter is allowed to modify the * next/prev to insert/remove/replace elements in the bucket list, but * the types and values of the individual buckets should not be altered. * - * The return value of a filter should be an APR status value. + * For the input and output filters, the return value of a filter should be + * an APR status value. For the init function, the return value should + * be an HTTP error code or OK if it was successful. * * @ingroup filter * @{ @@ -170,6 +177,7 @@ ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes); +typedef int (*ap_init_filter_func)(ap_filter_t *f); typedef union ap_filter_func { ap_out_filter_func out_func; @@ -242,6 +250,8 @@ const char *name; /** The function to call when this filter is invoked. */ ap_filter_func filter_func; + /** The function to call before the handlers are invoked. */ + ap_init_filter_func filter_init_func; /** The type of filter, either AP_FTYPE_CONTENT or AP_FTYPE_CONNECTION. * An AP_FTYPE_CONTENT filter modifies the data based on information * found in the content. An AP_FTYPE_CONNECTION filter modifies the @@ -259,8 +269,8 @@ * requests get an exact copy of the main requests filter chain. */ struct ap_filter_t { - /** The internal representation of this filter. This includes - * the filter's name, type, and the actual function pointer. + /** The internal representation of this filter. This includes + * the filter's name, type, and the actual function pointer. */ ap_filter_rec_t *frec; @@ -324,6 +334,7 @@ */ AP_DECLARE(ap_filter_rec_t *) ap_register_input_filter(const char *name, ap_in_filter_func filter_func, + ap_init_filter_func filter_init, ap_filter_type ftype); /** * This function is used to register an output filter with the system. @@ -339,6 +350,7 @@ */ AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name, ap_out_filter_func filter_func, + ap_init_filter_func filter_init, ap_filter_type ftype); /** Index: modules/experimental/mod_cache.c =================================================================== RCS file: /home/cvs/httpd-2.0/modules/experimental/mod_cache.c,v retrieving revision 1.44 diff -u -r1.44 mod_cache.c --- modules/experimental/mod_cache.c 5 Jun 2002 21:49:16 -0000 1.44 +++ modules/experimental/mod_cache.c 17 Jun 2002 05:35:08 -0000 @@ -981,6 +981,7 @@ */ ap_register_output_filter("CACHE_IN", cache_in_filter, + NULL, AP_FTYPE_CONTENT_SET); /* CACHE_OUT must go into the filter chain before SUBREQ_CORE to * handle subrequsts. Decrementing filter type by 1 ensures this @@ -988,9 +989,11 @@ */ ap_register_output_filter("CACHE_OUT", cache_out_filter, + NULL, AP_FTYPE_CONTENT_SET-1); ap_register_output_filter("CACHE_CONDITIONAL", cache_conditional_filter, + NULL, AP_FTYPE_CONTENT_SET); ap_hook_post_config(cache_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST); } Index: modules/experimental/mod_case_filter.c =================================================================== RCS file: /home/cvs/httpd-2.0/modules/experimental/mod_case_filter.c,v retrieving revision 1.11 diff -u -r1.11 mod_case_filter.c --- modules/experimental/mod_case_filter.c 29 Mar 2002 08:17:21 -0000 1.11 +++ modules/experimental/mod_case_filter.c 17 Jun 2002 05:35:08 -0000 @@ -97,7 +97,7 @@ static void CaseFilterRegisterHooks(apr_pool_t *p) { ap_hook_insert_filter(CaseFilterInsertFilter,NULL,NULL,APR_HOOK_MIDDLE); - ap_register_output_filter(s_szCaseFilterName,CaseFilterOutFilter, + ap_register_output_filter(s_szCaseFilterName,CaseFilterOutFilter,NULL, AP_FTYPE_RESOURCE); } Index: modules/experimental/mod_case_filter_in.c =================================================================== RCS file: /home/cvs/httpd-2.0/modules/experimental/mod_case_filter_in.c,v retrieving revision 1.15 diff -u -r1.15 mod_case_filter_in.c --- modules/experimental/mod_case_filter_in.c 29 Mar 2002 08:17:21 -0000 1.15 +++ modules/experimental/mod_case_filter_in.c 17 Jun 2002 05:35:08 -0000 @@ -181,7 +181,7 @@ { ap_hook_insert_filter(CaseFilterInInsertFilter, NULL, NULL, APR_HOOK_MIDDLE); - ap_register_input_filter(s_szCaseFilterName, CaseFilterInFilter, + ap_register_input_filter(s_szCaseFilterName, CaseFilterInFilter, NULL, AP_FTYPE_RESOURCE); } Index: modules/experimental/mod_charset_lite.c =================================================================== RCS file: /home/cvs/httpd-2.0/modules/experimental/mod_charset_lite.c,v retrieving revision 1.62 diff -u -r1.62 mod_charset_lite.c --- modules/experimental/mod_charset_lite.c 17 May 2002 11:33:09 -0000 1.62 +++ modules/experimental/mod_charset_lite.c 17 Jun 2002 05:35:13 -0000 @@ -1105,9 +1105,9 @@ { ap_hook_fixups(find_code_page, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_insert_filter(xlate_insert_filter, NULL, NULL, APR_HOOK_REALLY_LAST); - ap_register_output_filter(XLATEOUT_FILTER_NAME, xlate_out_filter, + ap_register_output_filter(XLATEOUT_FILTER_NAME, xlate_out_filter, NULL, AP_FTYPE_RESOURCE); - ap_register_input_filter(XLATEIN_FILTER_NAME, xlate_in_filter, + ap_register_input_filter(XLATEIN_FILTER_NAME, xlate_in_filter, NULL, AP_FTYPE_RESOURCE); } Index: modules/experimental/mod_ext_filter.c =================================================================== RCS file: /home/cvs/httpd-2.0/modules/experimental/mod_ext_filter.c,v retrieving revision 1.29 diff -u -r1.29 mod_ext_filter.c --- modules/experimental/mod_ext_filter.c 12 Jun 2002 23:59:30 -0000 1.29 +++ modules/experimental/mod_ext_filter.c 17 Jun 2002 05:35:13 -0000 @@ -311,12 +311,12 @@ */ if (filter->mode == OUTPUT_FILTER) { /* XXX need a way to ensure uniqueness among all filters */ - ap_register_output_filter(filter->name, ef_output_filter, AP_FTYPE_RESOURCE); + ap_register_output_filter(filter->name, ef_output_filter, NULL, AP_FTYPE_RESOURCE); } #if 0 /* no input filters yet */ else if (filter->mode == INPUT_FILTER) { /* XXX need a way to ensure uniqueness among all filters */ - ap_register_input_filter(filter->name, ef_input_filter, AP_FTYPE_RESOURCE); + ap_register_input_filter(filter->name, ef_input_filter, NULL, AP_FTYPE_RESOURCE); } #endif else { Index: modules/filters/mod_deflate.c =================================================================== RCS file: /home/cvs/httpd-2.0/modules/filters/mod_deflate.c,v retrieving revision 1.20 diff -u -r1.20 mod_deflate.c --- modules/filters/mod_deflate.c 14 Jun 2002 17:16:59 -0000 1.20 +++ modules/filters/mod_deflate.c 17 Jun 2002 05:35:13 -0000 @@ -760,9 +760,9 @@ static void register_hooks(apr_pool_t *p) { - ap_register_output_filter(deflateFilterName, deflate_out_filter, + ap_register_output_filter(deflateFilterName, deflate_out_filter, NULL, AP_FTYPE_CONTENT_SET); - ap_register_input_filter(deflateFilterName, deflate_in_filter, + ap_register_input_filter(deflateFilterName, deflate_in_filter, NULL, AP_FTYPE_CONTENT_SET); } Index: modules/filters/mod_include.c =================================================================== RCS file: /home/cvs/httpd-2.0/modules/filters/mod_include.c,v retrieving revision 1.226 diff -u -r1.226 mod_include.c --- modules/filters/mod_include.c 15 Jun 2002 05:41:48 -0000 1.226 +++ modules/filters/mod_include.c 17 Jun 2002 05:35:17 -0000 @@ -3296,6 +3296,36 @@ return NULL; } +static int includes_setup(ap_filter_t *f) +{ + include_dir_config *conf = + (include_dir_config *)ap_get_module_config(f->r->per_dir_config, + &include_module); + + /* Always unset the ETag/Last-Modified fields - see RFC2616 - 13.3.4. + * We don't know if we are going to be including a file or executing + * a program which may change the Last-Modified header or make the + * content completely dynamic. Therefore, we can't support these + * headers. + * Exception: XBitHack full means we *should* set the Last-Modified field. + */ + apr_table_unset(f->r->headers_out, "ETag"); + + /* Assure the platform supports Group protections. */ + if ((*conf->xbithack == xbithack_full) + && (f->r->finfo.valid & APR_FINFO_GPROT) + && (f->r->finfo.protection & APR_GEXECUTE)) { + ap_update_mtime(f->r, f->r->finfo.mtime); + ap_set_last_modified(f->r); + } + else { + f->r->no_local_copy = 1; + apr_table_unset(f->r->headers_out, "Last-Modified"); + } + + return OK; +} + static apr_status_t includes_filter(ap_filter_t *f, apr_bucket_brigade *b) { request_rec *r = f->r; @@ -3362,26 +3392,6 @@ */ apr_table_unset(f->r->headers_out, "Content-Length"); - /* Always unset the ETag/Last-Modified fields - see RFC2616 - 13.3.4. - * We don't know if we are going to be including a file or executing - * a program which may change the Last-Modified header or make the - * content completely dynamic. Therefore, we can't support these - * headers. - * Exception: XBitHack full means we *should* set the Last-Modified field. - */ - apr_table_unset(f->r->headers_out, "ETag"); - - /* Assure the platform supports Group protections */ - if ((*conf->xbithack == xbithack_full) - && (r->finfo.valid & APR_FINFO_GPROT) - && (r->finfo.protection & APR_GEXECUTE)) { - ap_update_mtime(r, r->finfo.mtime); - ap_set_last_modified(r); - } - else { - apr_table_unset(f->r->headers_out, "Last-Modified"); - } - return send_parsed_content(&b, r, f); } @@ -3529,7 +3539,8 @@ APR_REGISTER_OPTIONAL_FN(ap_register_include_handler); ap_hook_post_config(include_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST); ap_hook_fixups(include_fixup, NULL, NULL, APR_HOOK_LAST); - ap_register_output_filter("INCLUDES", includes_filter, AP_FTYPE_RESOURCE); + ap_register_output_filter("INCLUDES", includes_filter, includes_setup, + AP_FTYPE_RESOURCE); } module AP_MODULE_DECLARE_DATA include_module = Index: modules/http/http_core.c =================================================================== RCS file: /home/cvs/httpd-2.0/modules/http/http_core.c,v retrieving revision 1.303 diff -u -r1.303 http_core.c --- modules/http/http_core.c 12 Jun 2002 23:59:30 -0000 1.303 +++ modules/http/http_core.c 17 Jun 2002 05:35:17 -0000 @@ -330,15 +330,16 @@ ap_hook_create_request(http_create_request, NULL, NULL, APR_HOOK_REALLY_LAST); ap_http_input_filter_handle = ap_register_input_filter("HTTP_IN", ap_http_filter, - AP_FTYPE_PROTOCOL); + NULL, AP_FTYPE_PROTOCOL); ap_http_header_filter_handle = ap_register_output_filter("HTTP_HEADER", ap_http_header_filter, - AP_FTYPE_PROTOCOL); + NULL, AP_FTYPE_PROTOCOL); ap_chunk_filter_handle = - ap_register_output_filter("CHUNK", chunk_filter, AP_FTYPE_TRANSCODE); + ap_register_output_filter("CHUNK", chunk_filter, + NULL, AP_FTYPE_TRANSCODE); ap_byterange_filter_handle = ap_register_output_filter("BYTERANGE", ap_byterange_filter, - AP_FTYPE_PROTOCOL); + NULL, AP_FTYPE_PROTOCOL); ap_method_registry_init(p); } Index: modules/metadata/mod_headers.c =================================================================== RCS file: /home/cvs/httpd-2.0/modules/metadata/mod_headers.c,v retrieving revision 1.39 diff -u -r1.39 mod_headers.c --- modules/metadata/mod_headers.c 17 May 2002 11:33:10 -0000 1.39 +++ modules/metadata/mod_headers.c 17 Jun 2002 05:35:18 -0000 @@ -620,7 +620,8 @@ ap_hook_pre_config(header_pre_config,NULL,NULL,APR_HOOK_MIDDLE); ap_hook_insert_filter(ap_headers_insert_output_filter, NULL, NULL, APR_HOOK_LAST); ap_hook_fixups(ap_headers_fixup, NULL, NULL, APR_HOOK_LAST); - ap_register_output_filter("FIXUP_HEADERS_OUT", ap_headers_output_filter, AP_FTYPE_CONTENT_SET); + ap_register_output_filter("FIXUP_HEADERS_OUT", ap_headers_output_filter, + NULL, AP_FTYPE_CONTENT_SET); } module AP_MODULE_DECLARE_DATA headers_module = Index: modules/proxy/proxy_ftp.c =================================================================== RCS file: /home/cvs/httpd-2.0/modules/proxy/proxy_ftp.c,v retrieving revision 1.122 diff -u -r1.122 proxy_ftp.c --- modules/proxy/proxy_ftp.c 14 Jun 2002 17:14:57 -0000 1.122 +++ modules/proxy/proxy_ftp.c 17 Jun 2002 05:35:20 -0000 @@ -1926,7 +1926,8 @@ proxy_hook_scheme_handler(ap_proxy_ftp_handler, NULL, NULL, APR_HOOK_MIDDLE); proxy_hook_canon_handler(ap_proxy_ftp_canon, NULL, NULL, APR_HOOK_MIDDLE); /* filters */ - ap_register_output_filter("PROXY_SEND_DIR", ap_proxy_send_dir_filter, AP_FTYPE_RESOURCE); + ap_register_output_filter("PROXY_SEND_DIR", ap_proxy_send_dir_filter, + NULL, AP_FTYPE_RESOURCE); } module AP_MODULE_DECLARE_DATA proxy_ftp_module = { Index: modules/ssl/ssl_engine_io.c =================================================================== RCS file: /home/cvs/httpd-2.0/modules/ssl/ssl_engine_io.c,v retrieving revision 1.78 diff -u -r1.78 ssl_engine_io.c --- modules/ssl/ssl_engine_io.c 4 Jun 2002 07:12:26 -0000 1.78 +++ modules/ssl/ssl_engine_io.c 17 Jun 2002 05:35:21 -0000 @@ -943,8 +943,8 @@ void ssl_io_filter_register(apr_pool_t *p) { - ap_register_input_filter (ssl_io_filter, ssl_io_filter_Input, AP_FTYPE_CONNECTION + 5); - ap_register_output_filter (ssl_io_filter, ssl_io_filter_Output, AP_FTYPE_CONNECTION + 5); + ap_register_input_filter (ssl_io_filter, ssl_io_filter_Input, NULL, AP_FTYPE_CONNECTION + 5); + ap_register_output_filter (ssl_io_filter, ssl_io_filter_Output, NULL, AP_FTYPE_CONNECTION + 5); return; } Index: modules/test/mod_bucketeer.c =================================================================== RCS file: /home/cvs/httpd-2.0/modules/test/mod_bucketeer.c,v retrieving revision 1.13 diff -u -r1.13 mod_bucketeer.c --- modules/test/mod_bucketeer.c 31 May 2002 20:52:28 -0000 1.13 +++ modules/test/mod_bucketeer.c 17 Jun 2002 05:35:21 -0000 @@ -201,7 +201,7 @@ static void register_hooks(apr_pool_t * p) { ap_register_output_filter(bucketeerFilterName, bucketeer_out_filter, - AP_FTYPE_RESOURCE-1); + NULL, AP_FTYPE_RESOURCE-1); } static const command_rec bucketeer_filter_cmds[] = { Index: server/config.c =================================================================== RCS file: /home/cvs/httpd-2.0/server/config.c,v retrieving revision 1.152 diff -u -r1.152 config.c --- server/config.c 12 Jun 2002 23:59:31 -0000 1.152 +++ server/config.c 17 Jun 2002 05:35:23 -0000 @@ -335,6 +335,20 @@ return create_empty_config(p); } +static int ap_invoke_filter_init(ap_filter_t *filters) +{ + while (filters) { + if (filters->frec->filter_init_func) { + int result = filters->frec->filter_init_func(filters); + if (result != OK) { + return result; + } + } + filters = filters->next; + } + return OK; +} + AP_CORE_DECLARE(int) ap_invoke_handler(request_rec *r) { const char *handler; @@ -351,6 +365,19 @@ * fail, either your modules inserts something or it doesn't. rbb */ ap_run_insert_filter(r); + + /* Before continuing, allow each filter that is in the two chains to + * run their init function to let them do any magic before we could + * start generating data. + */ + result = ap_invoke_filter_init(r->input_filters); + if (result != OK) { + return result; + } + result = ap_invoke_filter_init(r->output_filters); + if (result != OK) { + return result; + } if (!r->handler) { handler = r->content_type ? r->content_type : ap_default_type(r); Index: server/core.c =================================================================== RCS file: /home/cvs/httpd-2.0/server/core.c,v retrieving revision 1.184 diff -u -r1.184 core.c --- server/core.c 15 Jun 2002 05:49:06 -0000 1.184 +++ server/core.c 17 Jun 2002 05:35:28 -0000 @@ -4094,21 +4094,22 @@ ap_core_input_filter_handle = ap_register_input_filter("CORE_IN", core_input_filter, - AP_FTYPE_NETWORK); + NULL, AP_FTYPE_NETWORK); ap_net_time_filter_handle = ap_register_input_filter("NET_TIME", net_time_filter, - AP_FTYPE_PROTOCOL); + NULL, AP_FTYPE_PROTOCOL); ap_content_length_filter_handle = ap_register_output_filter("CONTENT_LENGTH", ap_content_length_filter, - AP_FTYPE_PROTOCOL); + NULL, AP_FTYPE_PROTOCOL); ap_core_output_filter_handle = ap_register_output_filter("CORE", core_output_filter, - AP_FTYPE_NETWORK); + NULL, AP_FTYPE_NETWORK); ap_subreq_core_filter_handle = ap_register_output_filter("SUBREQ_CORE", ap_sub_req_output_filter, - AP_FTYPE_CONTENT_SET); - ap_old_write_func = ap_register_output_filter("OLD_WRITE", - ap_old_write_filter, AP_FTYPE_RESOURCE - 10); + NULL, AP_FTYPE_CONTENT_SET); + ap_old_write_func = + ap_register_output_filter("OLD_WRITE", ap_old_write_filter, + NULL, AP_FTYPE_RESOURCE - 10); } AP_DECLARE_DATA module core_module = { Index: server/util_filter.c =================================================================== RCS file: /home/cvs/httpd-2.0/server/util_filter.c,v retrieving revision 1.91 diff -u -r1.91 util_filter.c --- server/util_filter.c 17 May 2002 11:11:37 -0000 1.91 +++ server/util_filter.c 17 Jun 2002 05:35:28 -0000 @@ -234,6 +234,7 @@ static ap_filter_rec_t *register_filter(const char *name, ap_filter_func filter_func, + ap_init_filter_func filter_init, ap_filter_type ftype, filter_trie_node **reg_filter_set) { @@ -266,6 +267,7 @@ frec->name = normalized_name; } frec->filter_func = filter_func; + frec->filter_init_func = filter_init; frec->ftype = ftype; apr_pool_cleanup_register(FILTER_POOL, NULL, filter_cleanup, @@ -275,20 +277,24 @@ AP_DECLARE(ap_filter_rec_t *) ap_register_input_filter(const char *name, ap_in_filter_func filter_func, + ap_init_filter_func filter_init, ap_filter_type ftype) { ap_filter_func f; f.in_func = filter_func; - return register_filter(name, f, ftype, ®istered_input_filters); + return register_filter(name, f, filter_init, ftype, + ®istered_input_filters); } AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name, ap_out_filter_func filter_func, + ap_init_filter_func filter_init, ap_filter_type ftype) { ap_filter_func f; f.out_func = filter_func; - return register_filter(name, f, ftype, ®istered_output_filters); + return register_filter(name, f, filter_init, ftype, + ®istered_output_filters); } static ap_filter_t *add_any_filter_handle(ap_filter_rec_t *frec, void *ctx,