Any votes on this patch (even in concept if not on all the details)? If it looks like 
what
we want to do, I'll polish it up and commit it.

Bill

----- Original Message -----
From: "Bill Stoddard" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Sunday, March 17, 2002 11:39 PM
Subject: [PATCH] AddOutputFiltersbyType (revised)


> Introduces ap_rset_content_type()... This patch is not complete, I have not finished
> reviewing it (or doing the doc), but it should demonstrate Ryan and Sander's 
>suggestion
> for inserting resource filters based on content type. I am a bit concerned about some
> crufty code paths inserting the same filter multiple times into the same output 
>stream.
>
> Bill
>
> Index: include/http_core.h
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/include/http_core.h,v
> retrieving revision 1.63
> diff -u -r1.63 http_core.h
> --- include/http_core.h 13 Mar 2002 20:47:42 -0000 1.63
> +++ include/http_core.h 18 Mar 2002 04:26:19 -0000
> @@ -538,6 +538,9 @@
>      apr_array_header_t *sec_url;
>  } core_server_config;
>
> +/* for AddOutputFiltersByType in core.c */
> +void ap_add_output_filters_by_type(request_rec *r);
> +
>  /* for http_config.c */
>  void ap_core_reorder_directories(apr_pool_t *, server_rec *);
>
> Index: include/http_protocol.h
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/include/http_protocol.h,v
> retrieving revision 1.70
> diff -u -r1.70 http_protocol.h
> --- include/http_protocol.h 13 Mar 2002 20:47:42 -0000 1.70
> +++ include/http_protocol.h 18 Mar 2002 04:26:20 -0000
> @@ -330,6 +330,11 @@
>   */
>  AP_DECLARE(void) ap_clear_method_list(ap_method_list_t *l);
>
> +/**
> + *
> + */
> +AP_DECLARE(void) ap_rset_content_type(char *str, request_rec *r);
> +
>  /* Hmmm... could macrofy these for now, and maybe forever, though the
>   * definitions of the macros would get a whole lot hairier.
>   */
> Index: modules/dav/main/mod_dav.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/dav/main/mod_dav.c,v
> retrieving revision 1.73
> diff -u -r1.73 mod_dav.c
> --- modules/dav/main/mod_dav.c 13 Mar 2002 20:47:45 -0000 1.73
> +++ modules/dav/main/mod_dav.c 18 Mar 2002 04:26:25 -0000
> @@ -367,7 +367,7 @@
>      /* ### I really don't think this is needed; gotta test */
>      r->status_line = ap_get_status_line(status);
>
> -    r->content_type = "text/html";
> +    ap_rset_content_type("text/html", r);
>
>      /* since we're returning DONE, ensure the request body is consumed. */
>      (void) ap_discard_request_body(r);
> @@ -404,7 +404,7 @@
>      /* ### I really don't think this is needed; gotta test */
>      r->status_line = ap_get_status_line(err->status);
>
> -    r->content_type = DAV_XML_CONTENT_TYPE;
> +    ap_rset_content_type(DAV_XML_CONTENT_TYPE, r);
>
>      /* since we're returning DONE, ensure the request body is consumed. */
>      (void) ap_discard_request_body(r);
> @@ -477,7 +477,7 @@
>  {
>      /* Set the correct status and Content-Type */
>      r->status = status;
> -    r->content_type = DAV_XML_CONTENT_TYPE;
> +    ap_rset_content_type(DAV_XML_CONTENT_TYPE, r);
>
>      /* Send the headers and actual multistatus response now... */
>      ap_rputs(DAV_XML_HEADER DEBUG_CR
> @@ -1715,7 +1715,7 @@
>
>      /* send the options response */
>      r->status = HTTP_OK;
> -    r->content_type = DAV_XML_CONTENT_TYPE;
> +    ap_rset_content_type(DAV_XML_CONTENT_TYPE, r);
>
>      /* send the headers and response body */
>      ap_rputs(DAV_XML_HEADER DEBUG_CR
> @@ -2942,7 +2942,7 @@
>      (*locks_hooks->close_lockdb)(lockdb);
>
>      r->status = HTTP_OK;
> -    r->content_type = DAV_XML_CONTENT_TYPE;
> +    ap_rset_content_type(DAV_XML_CONTENT_TYPE, r);
>
>      ap_rputs(DAV_XML_HEADER DEBUG_CR "<D:prop xmlns:D=\"DAV:\">" DEBUG_CR, r);
>      if (lock == NULL)
> @@ -3910,7 +3910,7 @@
>
>      /* send the report response */
>      r->status = HTTP_OK;
> -    r->content_type = DAV_XML_CONTENT_TYPE;
> +    ap_rset_content_type(DAV_XML_CONTENT_TYPE, r);
>
>      /* send the headers and response body */
>      ap_rputs(DAV_XML_HEADER DEBUG_CR, r);
> @@ -4155,7 +4155,7 @@
>         is going to do something different (i.e. an error), then it must
>         return a dav_error, and we'll reset these values properly. */
>      r->status = HTTP_OK;
> -    r->content_type = "text/xml";
> +    ap_rset_content_type("text/xml", r);
>
>      /* ### should we do any preliminary response generation? probably not,
>         ### because we may have an error, thus demanding something else in
> Index: modules/experimental/cache_storage.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/experimental/cache_storage.c,v
> retrieving revision 1.18
> diff -u -r1.18 cache_storage.c
> --- modules/experimental/cache_storage.c 13 Mar 2002 20:47:46 -0000 1.18
> +++ modules/experimental/cache_storage.c 18 Mar 2002 04:26:25 -0000
> @@ -237,7 +237,7 @@
>          return rv;
>      }
>
> -    r->content_type = apr_pstrdup(r->pool, info->content_type);
> +    ap_rset_content_type(apr_pstrdup(r->pool, info->content_type), r);
>      r->filename = apr_pstrdup(r->pool, info->filename );
>
>      return APR_SUCCESS;
> Index: modules/experimental/mod_example.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/experimental/mod_example.c,v
> retrieving revision 1.34
> diff -u -r1.34 mod_example.c
> --- modules/experimental/mod_example.c 13 Mar 2002 20:47:46 -0000 1.34
> +++ modules/experimental/mod_example.c 18 Mar 2002 04:26:27 -0000
> @@ -552,7 +552,7 @@
>       * We also need to start a timer so the server can know if the connexion
>       * is broken.
>       */
> -    r->content_type = "text/html";
> +    ap_rset_content_type("text/html", r);
>      /*
>       * If we're only supposed to send header information (HEAD request), we're
>       * already there.
> Index: modules/filters/mod_include.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/filters/mod_include.c,v
> retrieving revision 1.199
> diff -u -r1.199 mod_include.c
> --- modules/filters/mod_include.c 13 Mar 2002 20:47:47 -0000 1.199
> +++ modules/filters/mod_include.c 18 Mar 2002 04:26:30 -0000
> @@ -3427,7 +3427,7 @@
>      if (r->handler && (strcmp(r->handler, "server-parsed") == 0))
>      {
>          if (!r->content_type || !*r->content_type) {
> -            r->content_type = "text/html";
> +            ap_rset_content_type("text/html", r);
>          }
>          r->handler = "default-handler";
>      }
> Index: modules/generators/mod_autoindex.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/generators/mod_autoindex.c,v
> retrieving revision 1.100
> diff -u -r1.100 mod_autoindex.c
> --- modules/generators/mod_autoindex.c 13 Mar 2002 20:47:48 -0000 1.100
> +++ modules/generators/mod_autoindex.c 18 Mar 2002 04:26:32 -0000
> @@ -1895,9 +1895,9 @@
>      }
>
>  #if APR_HAS_UNICODE_FS
> -    r->content_type = "text/html;charset=utf-8";
> +    ap_rset_content_type("text/html;charset=utf-8", r);
>  #else
> -    r->content_type = "text/html";
> +    ap_rset_content_type("text/html", r);
>  #endif
>      if (autoindex_opts & TRACK_MODIFIED) {
>          ap_update_mtime(r, r->finfo.mtime);
> Index: modules/generators/mod_cgi.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/generators/mod_cgi.c,v
> retrieving revision 1.120
> diff -u -r1.120 mod_cgi.c
> --- modules/generators/mod_cgi.c 14 Mar 2002 22:19:13 -0000 1.120
> +++ modules/generators/mod_cgi.c 18 Mar 2002 04:26:33 -0000
> @@ -782,7 +782,7 @@
>       * typing rules would have called it something else.
>       */
>
> -    rr->content_type = CGI_MAGIC_TYPE;
> +    ap_rset_content_type(CGI_MAGIC_TYPE, rr);
>
>      /* Run it. */
>
> Index: modules/generators/mod_cgid.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/generators/mod_cgid.c,v
> retrieving revision 1.116
> diff -u -r1.116 mod_cgid.c
> --- modules/generators/mod_cgid.c 14 Mar 2002 22:19:13 -0000 1.116
> +++ modules/generators/mod_cgid.c 18 Mar 2002 04:26:34 -0000
> @@ -1205,8 +1205,7 @@
>      /* Force sub_req to be treated as a CGI request, even if ordinary
>       * typing rules would have called it something else.
>       */
> -
> -    rr->content_type = CGI_MAGIC_TYPE;
> +    ap_rset_content_type(CGI_MAGIC_TYPE, rr);
>
>      /* Run it. */
>
> Index: modules/generators/mod_info.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/generators/mod_info.c,v
> retrieving revision 1.41
> diff -u -r1.41 mod_info.c
> --- modules/generators/mod_info.c 13 Mar 2002 20:47:48 -0000 1.41
> +++ modules/generators/mod_info.c 18 Mar 2002 04:26:35 -0000
> @@ -377,7 +377,7 @@
>      if (r->method_number != M_GET)
>   return DECLINED;
>
> -    r->content_type = "text/html";
> +    ap_rset_content_type("text/html", r);
>      if (r->header_only) {
>          return 0;
>      }
> Index: modules/generators/mod_status.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/generators/mod_status.c,v
> retrieving revision 1.61
> diff -u -r1.61 mod_status.c
> --- modules/generators/mod_status.c 15 Mar 2002 15:30:22 -0000 1.61
> +++ modules/generators/mod_status.c 18 Mar 2002 04:26:35 -0000
> @@ -283,7 +283,7 @@
>      if (r->method_number != M_GET)
>          return DECLINED;
>
> -    r->content_type = "text/html";
> +    ap_rset_content_type("text/html", r);
>
>      /*
>       * Simple table-driven form data set parser that lets you alter the header
> @@ -312,7 +312,7 @@
>                      no_table_report = 1;
>                      break;
>                  case STAT_OPT_AUTO:
> -                    r->content_type = "text/plain";
> +                    ap_rset_content_type("text/plain", r);
>                      short_report = 1;
>                      break;
>                  }
> Index: modules/http/http_protocol.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/http/http_protocol.c,v
> retrieving revision 1.394
> diff -u -r1.394 http_protocol.c
> --- modules/http/http_protocol.c 13 Mar 2002 20:47:49 -0000 1.394
> +++ modules/http/http_protocol.c 18 Mar 2002 04:26:37 -0000
> @@ -1013,7 +1013,7 @@
>          return rv;
>      }
>
> -    r->content_type = "message/http";
> +    ap_rset_content_type("message/http", r);
>
>      /* Now we recreate the request, and echo it back */
>
> @@ -1121,6 +1121,17 @@
>                         apr_array_pstrcat(r->pool, varies, ','));
>      }
>  }
> +AP_DECLARE(void) ap_rset_content_type(char *ct, request_rec *r)
> +{
> +    r->content_type = ct;
> +
> +    /* Insert filters requested by the AddOutputFiltersByType
> +     * configuration directive. Content-type filters must be
> +     * inserted after the content handlers have run because
> +     * only then, do we reliably know the content-type.
> +     */
> +    ap_add_output_filters_by_type(r);
> +}
>
>  typedef struct header_filter_ctx {
>      int headers_sent;
> @@ -1907,7 +1918,7 @@
>          r->content_languages = NULL;
>          r->content_encoding = NULL;
>          r->clength = 0;
> -        r->content_type = "text/html; charset=iso-8859-1";
> +        ap_rset_content_type("text/html; charset=iso-8859-1", r);
>
>          if ((status == HTTP_METHOD_NOT_ALLOWED)
>              || (status == HTTP_NOT_IMPLEMENTED)) {
> @@ -2461,10 +2472,10 @@
>
>          if (num_ranges > 1) {
>              ctx->orig_ct = r->content_type;
> -            r->content_type = apr_pstrcat(r->pool, "multipart",
> -                                          use_range_x(r) ? "/x-" : "/",
> -                                          "byteranges; boundary=",
> -                                          r->boundary, NULL);
> +            ap_rset_content_type(apr_pstrcat(r->pool, "multipart",
> +                                             use_range_x(r) ? "/x-" : "/",
> +                                             "byteranges; boundary=",
> +                                             r->boundary, NULL), r);
>          }
>
>          /* create a brigade in case we never call ap_save_brigade() */
> Index: modules/http/http_request.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/http/http_request.c,v
> retrieving revision 1.131
> diff -u -r1.131 http_request.c
> --- modules/http/http_request.c 13 Mar 2002 20:47:49 -0000 1.131
> +++ modules/http/http_request.c 18 Mar 2002 04:26:38 -0000
> @@ -386,7 +386,7 @@
>      r->args = rr->args;
>      r->finfo = rr->finfo;
>      r->handler = rr->handler;
> -    r->content_type = rr->content_type;
> +    ap_rset_content_type(rr->content_type, r);
>      r->content_encoding = rr->content_encoding;
>      r->content_languages = rr->content_languages;
>      r->per_dir_config = rr->per_dir_config;
> @@ -428,7 +428,7 @@
>      int access_status;
>      request_rec *new = internal_internal_redirect(new_uri, r);
>      if (r->handler)
> -        new->content_type = r->content_type;
> +        ap_rset_content_type(r->content_type, new);
>      access_status = ap_process_request_internal(new);
>      if (access_status == OK) {
>          if ((access_status = ap_invoke_handler(new)) != 0) {
> Index: modules/http/mod_mime.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/http/mod_mime.c,v
> retrieving revision 1.77
> diff -u -r1.77 mod_mime.c
> --- modules/http/mod_mime.c 13 Mar 2002 20:47:49 -0000 1.77
> +++ modules/http/mod_mime.c 18 Mar 2002 04:26:38 -0000
> @@ -76,7 +76,7 @@
>  #include "http_config.h"
>  #include "http_log.h"
>  #include "http_request.h"
> -
> +#include "http_protocol.h"
>
>  /* XXXX - fix me / EBCDIC
>   *        there was a cludge here which would use its
> @@ -737,7 +737,7 @@
>      int found_metadata = 0;
>
>      if (r->finfo.filetype == APR_DIR) {
> -        r->content_type = DIR_MAGIC_TYPE;
> +        ap_rset_content_type(DIR_MAGIC_TYPE, r);
>          return OK;
>      }
>
> @@ -786,7 +786,7 @@
>          if (exinfo == NULL || !exinfo->forced_type) {
>              if ((type = apr_hash_get(mime_type_extensions, ext,
>                                       APR_HASH_KEY_STRING)) != NULL) {
> -                r->content_type = type;
> +                ap_rset_content_type((char*) type, r);
>                  found = 1;
>              }
>          }
> @@ -794,7 +794,7 @@
>          if (exinfo != NULL) {
>
>              if (exinfo->forced_type) {
> -                r->content_type = exinfo->forced_type;
> +                ap_rset_content_type(exinfo->forced_type, r);
>                  found = 1;
>              }
>
> @@ -878,29 +878,29 @@
>
>   if ((ctp = analyze_ct(r, r->content_type))) {
>       param *pp = ctp->param;
> -     r->content_type = apr_pstrcat(r->pool, ctp->type, "/",
> -      ctp->subtype, NULL);
> +     ap_rset_content_type(apr_pstrcat(r->pool, ctp->type, "/",
> +                                             ctp->subtype, NULL), r);
>       while (pp != NULL) {
>    if (charset && !strcmp(pp->attr, "charset")) {
>        if (!override) {
> -   r->content_type = apr_pstrcat(r->pool, r->content_type,
> -           "; charset=", charset,
> -           NULL);
> +   ap_rset_content_type(apr_pstrcat(r->pool, r->content_type,
> +                                                         "; charset=", charset,
> +                                                         NULL), r);
>     override = 1;
>        }
>    }
>    else {
> -      r->content_type = apr_pstrcat(r->pool, r->content_type,
> -       "; ", pp->attr,
> -       "=", pp->val,
> -       NULL);
> +      ap_rset_content_type(apr_pstrcat(r->pool, r->content_type,
> +                                                     "; ", pp->attr,
> +                                                     "=", pp->val,
> +                                                     NULL), r);
>    }
>    pp = pp->next;
>       }
>       if (charset && !override) {
> -  r->content_type = apr_pstrcat(r->pool, r->content_type,
> -          "; charset=", charset,
> -          NULL);
> +  ap_rset_content_type(apr_pstrcat(r->pool, r->content_type,
> +                                                 "; charset=", charset,
> +                                                 NULL), r);
>       }
>   }
>      }
> Index: modules/mappers/mod_imap.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/mappers/mod_imap.c,v
> retrieving revision 1.35
> diff -u -r1.35 mod_imap.c
> --- modules/mappers/mod_imap.c 13 Mar 2002 20:47:50 -0000 1.35
> +++ modules/mappers/mod_imap.c 18 Mar 2002 04:26:39 -0000
> @@ -521,7 +521,7 @@
>
>  static void menu_header(request_rec *r, char *menu)
>  {
> -    r->content_type = "text/html";
> +    ap_rset_content_type("text/html", r);
>
>      ap_rvputs(r, DOCTYPE_HTML_3_2, "<html><head>\n<title>Menu for ", r->uri,
>             "</title>\n</head><body>\n", NULL);
> Index: modules/mappers/mod_negotiation.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/mappers/mod_negotiation.c,v
> retrieving revision 1.98
> diff -u -r1.98 mod_negotiation.c
> --- modules/mappers/mod_negotiation.c 13 Mar 2002 20:47:50 -0000 1.98
> +++ modules/mappers/mod_negotiation.c 18 Mar 2002 04:26:42 -0000
> @@ -1115,7 +1115,7 @@
>           * might be doing.
>           */
>          if (sub_req->handler && !sub_req->content_type) {
> -            sub_req->content_type = CGI_MAGIC_TYPE;
> +            ap_rset_content_type(CGI_MAGIC_TYPE, sub_req);
>          }
>
>          /*
> Index: modules/mappers/mod_rewrite.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/mappers/mod_rewrite.c,v
> retrieving revision 1.101
> diff -u -r1.101 mod_rewrite.c
> --- modules/mappers/mod_rewrite.c 14 Mar 2002 22:19:14 -0000 1.101
> +++ modules/mappers/mod_rewrite.c 18 Mar 2002 04:26:45 -0000
> @@ -1306,7 +1306,7 @@
>      else {
>          rewritelog(r, 1, "force filename %s to have MIME-type '%s'",
>                     r->filename, t);
> -        r->content_type = t;
> +        ap_rset_content_type(t, r);
>          return OK;
>      }
>  }
> @@ -1954,7 +1954,7 @@
>                   */
>                  rewritelog(r, 1, "[per-dir %s] force %s to have MIME-type "
>                             "'%s'", perdir, r->filename, p->forced_mimetype);
> -                r->content_type = p->forced_mimetype;
> +                ap_rset_content_type(p->forced_mimetype, r);
>              }
>          }
>          return 2;
> Index: modules/metadata/mod_cern_meta.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/metadata/mod_cern_meta.c,v
> retrieving revision 1.36
> diff -u -r1.36 mod_cern_meta.c
> --- modules/metadata/mod_cern_meta.c 13 Mar 2002 20:47:52 -0000 1.36
> +++ modules/metadata/mod_cern_meta.c 18 Mar 2002 04:26:45 -0000
> @@ -165,6 +165,7 @@
>  #include "util_script.h"
>  #include "http_log.h"
>  #include "http_request.h"
> +#include "http_protocol.h"
>  #include "apr_lib.h"
>
>  #define DIR_CMD_PERMS OR_INDEXES
> @@ -292,7 +293,7 @@
>
>       tmp = apr_pstrdup(r->pool, l);
>       ap_content_type_tolower(tmp);
> -     r->content_type = tmp;
> +     ap_rset_content_type(tmp, r);
>   }
>   else if (!strcasecmp(w, "Status")) {
>       sscanf(l, "%d", &r->status);
> Index: modules/metadata/mod_mime_magic.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/metadata/mod_mime_magic.c,v
> retrieving revision 1.53
> diff -u -r1.53 mod_mime_magic.c
> --- modules/metadata/mod_mime_magic.c 14 Mar 2002 22:19:14 -0000 1.53
> +++ modules/metadata/mod_mime_magic.c 18 Mar 2002 04:26:47 -0000
> @@ -833,7 +833,7 @@
>   /* XXX: this could be done at config time I'm sure... but I'm
>    * confused by all this magic_rsl stuff. -djg */
>   ap_content_type_tolower(tmp);
> - r->content_type = tmp;
> + ap_rset_content_type(tmp, r);
>      }
>      if (state == rsl_encoding) {
>          char *tmp;
> @@ -2364,7 +2364,7 @@
>
>      /* extract content type/encoding/language from sub-request */
>      if (sub->content_type) {
> - r->content_type = apr_pstrdup(r->pool, sub->content_type);
> + ap_rset_content_type(apr_pstrdup(r->pool, sub->content_type), r);
>  #if MIME_MAGIC_DEBUG
>   ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
>        MODNAME ": subrequest %s got %s",
> Index: modules/proxy/proxy_ftp.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/proxy/proxy_ftp.c,v
> retrieving revision 1.113
> diff -u -r1.113 proxy_ftp.c
> --- modules/proxy/proxy_ftp.c 9 Mar 2002 07:15:33 -0000 1.113
> +++ modules/proxy/proxy_ftp.c 18 Mar 2002 04:26:48 -0000
> @@ -1710,7 +1710,7 @@
>
>      /* set content-type */
>      if (dirlisting) {
> -        r->content_type = "text/html";
> +        ap_rset_content_type("text/html", r);
>      }
>      else {
>          if (r->content_type) {
> @@ -1718,7 +1718,7 @@
>                       "proxy: FTP: Content-Type set to %s", r->content_type);
>          }
>          else {
> -            r->content_type = ap_default_type(r);
> +            ap_rset_content_type(ap_default_type(r), r);
>          }
>          if (xfer_type != 'A' && size != NULL) {
>              /* We "trust" the ftp server to really serve (size) bytes... */
> Index: modules/proxy/proxy_http.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/proxy/proxy_http.c,v
> retrieving revision 1.135
> diff -u -r1.135 proxy_http.c
> --- modules/proxy/proxy_http.c 13 Mar 2002 20:47:53 -0000 1.135
> +++ modules/proxy/proxy_http.c 18 Mar 2002 04:26:49 -0000
> @@ -701,7 +701,7 @@
>                                                    "close");
>                  ap_proxy_clear_connection(p, r->headers_out);
>                  if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {
> -                    r->content_type = apr_pstrdup(p, buf);
> +                    ap_rset_content_type(apr_pstrdup(p, buf), r);
>                  }
>                  ap_proxy_pre_http_request(origin,rp);
>              }
> Index: server/core.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/server/core.c,v
> retrieving revision 1.162
> diff -u -r1.162 core.c
> --- server/core.c 13 Mar 2002 20:47:59 -0000 1.162
> +++ server/core.c 18 Mar 2002 04:26:52 -0000
> @@ -2545,6 +2545,43 @@
>
>      return NULL;
>  }
> +/*
> + * Insert filters requested by the AddOutputFiltersByType
> + * configuration directive. We cannot add filters based
> + * on content-type until after the handler has started
> + * to run. Only then do we reliabily know the content-type.
> + */
> +void ap_add_output_filters_by_type(request_rec *r)
> +{
> +    core_dir_config *conf;
> +    const char *ctype, *ctypes;
> +
> +    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
> +                                                   &core_module);
> +
> +    /* We can't do anything with proxy requests, no content-types or if
> +     * we don't have a filter configured.
> +     */
> +    if (r->proxyreq != PROXYREQ_NONE || !r->content_type ||
> +        !conf->ct_output_filters) {
> +        return;
> +    }
> +
> +    ctypes = r->content_type;
> +
> +    /* We must be able to handle decorated content-types.  */
> +    while (*ctypes && (ctype = ap_getword(r->pool, &ctypes, ';'))) {
> +        ap_filter_rec_t *ct_filter;
> +        ct_filter = apr_hash_get(conf->ct_output_filters, ctype,
> +                                 APR_HASH_KEY_STRING);
> +        while (ct_filter) {
> +            ap_add_output_filter(ct_filter->name, NULL, r, r->connection);
> +            ct_filter = ct_filter->next;
> +        }
> +    }
> +
> +    return;
> +}
>
>  static apr_status_t writev_it_all(apr_socket_t *s,
>                                    struct iovec *vec, int nvec,
> @@ -3053,7 +3090,7 @@
>      /* Check for overrides with ForceType / SetHandler
>       */
>      if (conf->mime_type && strcmp(conf->mime_type, "none"))
> -        r->content_type = conf->mime_type;
> +        ap_rset_content_type((char*) conf->mime_type, r);
>
>      if (conf->handler && strcmp(conf->handler, "none"))
>          r->handler = conf->handler;
> @@ -3076,37 +3113,7 @@
>      return OK;
>  }
>
> -static int core_filters_type(request_rec *r)
> -{
> -    core_dir_config *conf;
> -    const char *ctype, *ctypes;
> -
> -    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
> -                                                   &core_module);
> -
> -    /* We can't do anything with proxy requests, no content-types or if
> -     * we don't have a filter configured.
> -     */
> -    if (r->proxyreq != PROXYREQ_NONE || !r->content_type ||
> -        !conf->ct_output_filters) {
> -        return OK;
> -    }
> -
> -    ctypes = r->content_type;
> -
> -    /* We must be able to handle decorated content-types.  */
> -    while (*ctypes && (ctype = ap_getword(r->pool, &ctypes, ';'))) {
> -        ap_filter_rec_t *ct_filter;
> -        ct_filter = apr_hash_get(conf->ct_output_filters, ctype,
> -                                 APR_HASH_KEY_STRING);
> -        while (ct_filter) {
> -            ap_add_output_filter(ct_filter->name, NULL, r, r->connection);
> -            ct_filter = ct_filter->next;
> -        }
> -    }
>
> -    return OK;
> -}
>
>  static int default_handler(request_rec *r)
>  {
> @@ -4014,7 +4021,6 @@
>      /* FIXME: I suspect we can eliminate the need for these do_nothings - Ben */
>      ap_hook_type_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST);
>      ap_hook_fixups(core_override_type,NULL,NULL,APR_HOOK_REALLY_FIRST);
> -    ap_hook_fixups(core_filters_type,NULL,NULL,APR_HOOK_MIDDLE);
>      ap_hook_access_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST);
>      ap_hook_create_request(core_create_req, NULL, NULL, APR_HOOK_MIDDLE);
>      APR_OPTIONAL_HOOK(proxy, create_req, core_create_proxy_req, NULL, NULL,
> Index: server/util_script.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/server/util_script.c,v
> retrieving revision 1.71
> diff -u -r1.71 util_script.c
> --- server/util_script.c 13 Mar 2002 20:48:01 -0000 1.71
> +++ server/util_script.c 18 Mar 2002 04:26:53 -0000
> @@ -569,7 +569,7 @@
>
>       tmp = apr_pstrdup(r->pool, l);
>       ap_content_type_tolower(tmp);
> -     r->content_type = tmp;
> +     ap_rset_content_type(tmp, r);
>   }
>   /*
>    * If the script returned a specific status, that's what
>
>
>
>
> ----- Original Message -----
> From: "Ryan Bloom" <[EMAIL PROTECTED]>
> To: <[EMAIL PROTECTED]>; <[EMAIL PROTECTED]>; "'Bill Stoddard'" 
><[EMAIL PROTECTED]>
> Sent: Friday, March 15, 2002 12:39 PM
> Subject: RE: [PATCH] AddOutputFiltersbyType
>
>
> > Sander and I were just discussing this on IRC, because there is a
> > chicken and egg problem here.  The problem is that the filter order is
> > defined at registration time, which means that the filter order problem
> > can't be solved with a new filter.
> >
> > The only clean way to implement this (IMHO), is to create a function
> > that sets the content-type.  That function would then be able to call
> > AddOutputFilterByType automatically, and it would insert filters
> > correctly at the correct times.
> >
> > This would also allow us to make the content-type in the request-rec a
> > const string, because the only safe way to change it is through the
> > accessor.
> >
> > This idea came from both Sander and I, but any mangling done in this
> > description is mine alone.
> >
> > Ryan
> >
> > ----------------------------------------------
> > Ryan Bloom                  [EMAIL PROTECTED]
> > 645 Howard St.              [EMAIL PROTECTED]
> > San Francisco, CA
> >
> > > -----Original Message-----
> > > From: Ryan Bloom [mailto:[EMAIL PROTECTED]]
> > > Sent: Friday, March 15, 2002 9:22 AM
> > > To: 'Bill Stoddard'; [EMAIL PROTECTED]
> > > Subject: RE: [PATCH] AddOutputFiltersbyType
> > >
> > >
> > > > > > The essential feature of this patch is that
> > > > > > ap_add_output_filters_by_type() is called out
> > > > > > of the ap_http_header_filter.
> > > > >
> > > > > You can't solve this problem this way.  The problem here, is that
> > > the
> > > > > first time down the filter stack, the data won't go through the
> > > correct
> > > > > filters.  Think of what would happen if you had CGI script that
> > > output
> > > > > text/html, and you had
> > > > >
> > > > > AddOutputFiltersByType INCLUDES text/html.
> > > > >
> > > > > With this patch, it would be possible to miss SSI tags in the
> > first
> > > > > chunk of data.
> > > > Not sure I understand why this is the case.  The call to
> > > > ap_add_output_filters_by_type()
> > > > is being called right before the call to insert the chunked encoding
> > > > filter. If what you
> > > > say is true, then wouldn't the problem exist with the chunked
> > encoding
> > > > filter as well?
> > >
> > > Nope.  The thing is that we insert filters in a defined order,
> > specified
> > > by the filter type.  The chunked filter is a protocol filter, so it is
> > > by definition after the HTTP_HEADER filter.  However, the INLCUDES
> > > filter is a RESOURCE filter, so it is by definition before
> > HTTP_HEADER.
> > >
> > > > > The only way to do this, is to have a filter at the end of the
> > > RESOURCE
> > > > > and CONTENT_SET filter stacks.  That filter would add more
> > filters,
> > > and
> > > > > then move itself to below those new filters to check if the
> > > content-type
> > > > > has changed.
> > > >
> > > > Yep, I considered this and will implement it if this is what we
> > really
> > > > need to do.
> > >
> > > Take a look at my comments above, if they aren't clear, I will try to
> > go
> > > into more detail.  BTW, the hard part about doing this, is that we
> > have
> > > to re-insert the AddOutputFilterByType filter _after_ the new filter
> > > that is being added, and we need to be sure that the new filter
> > actually
> > > sees the content, which is NOT going to be easy to do, because of the
> > > filter order.
> > >
> > > In reality, I don't see a good way to implement this feature.
> > >
> > > Ryan
> > >
> >
> >
>

Reply via email to