httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From c...@apache.org
Subject cvs commit: httpd-2.0/modules/metadata mod_expires.c
Date Wed, 14 May 2003 17:39:14 GMT
coar        2003/05/14 10:39:14

  Modified:    modules/metadata mod_expires.c
  Log:
  	if there are any ExpiresByType directives for the current
  	scope, defer the setting of the expiration header fields
  	to an output filter, which can then apply any ExpiresByType
  	or ExpiresDefault settings -- including to dynamic documents.
  
  Revision  Changes    Path
  1.41      +145 -50   httpd-2.0/modules/metadata/mod_expires.c
  
  Index: mod_expires.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/metadata/mod_expires.c,v
  retrieving revision 1.40
  retrieving revision 1.41
  diff -u -u -r1.40 -r1.41
  --- mod_expires.c	3 Feb 2003 17:53:09 -0000	1.40
  +++ mod_expires.c	14 May 2003 17:39:14 -0000	1.41
  @@ -212,6 +212,11 @@
       apr_table_t *expiresbytype;
   } expires_dir_config;
   
  +typedef struct {
  +    int defaulted;
  +    apr_table_t *expfields;
  +} expires_interphase_t;
  +
   /* from mod_dir, why is this alias used?
    */
   #define DIR_CMD_PERMS OR_INDEXES
  @@ -416,59 +421,23 @@
       return new;
   }
   
  -static int add_expires(request_rec *r)
  +/*
  + * Handle the setting of the expiration response header fields according
  + * to our criteria.
  + */
  +
  +static int set_expiration_fields(request_rec *r, const char *code,
  +                                 apr_table_t *t)
   {
  -    expires_dir_config *conf;
  -    char *code;
       apr_time_t base;
       apr_time_t additional;
       apr_time_t expires;
       int additional_sec;
       char *timestr;
  +    expires_interphase_t *notes;
   
  -    if (ap_is_HTTP_ERROR(r->status))       /* Don't add Expires headers to errors */
  -        return DECLINED;
  -
  -    if (r->main != NULL)        /* Say no to subrequests */
  -        return DECLINED;
  -
  -    conf = (expires_dir_config *) ap_get_module_config(r->per_dir_config, &expires_module);
  -    if (conf == NULL) {
  -        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  -                    "internal error: %s", r->filename);
  -        return HTTP_INTERNAL_SERVER_ERROR;
  -    }
  -
  -    if (conf->active != ACTIVE_ON)
  -        return DECLINED;
  -
  -    /* we perhaps could use the default_type(r) in its place but that
  -     * may be 2nd guesing the desired configuration...  calling table_get
  -     * with a NULL key will SEGV us
  -     *
  -     * I still don't know *why* r->content_type would ever be NULL, this
  -     * is possibly a result of fixups being called in many different
  -     * places.  Fixups is probably the wrong place to be doing all this
  -     * work...  Bah.
  -     *
  -     * Changed as of 08.Jun.96 don't DECLINE, look for an ExpiresDefault.
  -     */
  -    if (r->content_type == NULL)
  -        code = NULL;
  -    else
  -        code = (char *) apr_table_get(conf->expiresbytype, 
  -		ap_field_noparam(r->pool, r->content_type));
  -
  -    if (code == NULL) {
  -        /* no expires defined for that type, is there a default? */
  -        code = conf->expiresdefault;
  -
  -        if (code[0] == '\0')
  -            return OK;
  -    }
  -
  -    /* we have our code */
  -
  +    notes = (expires_interphase_t *) ap_get_module_config(r->request_config,
  +                                                          &expires_module);
       switch (code[0]) {
       case 'M':
   	if (r->finfo.filetype == 0) { 
  @@ -499,17 +468,143 @@
       }
   
       expires = base + additional;
  -    apr_table_mergen(r->headers_out, "Cache-Control",
  -		    apr_psprintf(r->pool, "max-age=%" APR_TIME_T_FMT,
  -                                 apr_time_sec(expires - r->request_time)));
  +    apr_table_mergen(t, "Cache-Control",
  +                     apr_psprintf(r->pool, "max-age=%" APR_TIME_T_FMT,
  +                                  apr_time_sec(expires - r->request_time)));
       timestr = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
       apr_rfc822_date(timestr, expires);
  -    apr_table_setn(r->headers_out, "Expires", timestr);
  +    apr_table_setn(t, "Expires", timestr);
       return OK;
   }
   
  +/*
  + * Output filter to set the Expires response header field
  + * according to the content-type of the response -- if it hasn't
  + * already been set.
  + */
  +static apr_status_t expires_by_type_filter(ap_filter_t *f,
  +                                           apr_bucket_brigade *b)
  +{
  +    request_rec *r;
  +    expires_dir_config *conf;
  +    expires_interphase_t *notes;
  +    const char *bytype_expiry;
  +    apr_table_t *t;
  +
  +    r = f->r;
  +    conf = (expires_dir_config *) ap_get_module_config(r->per_dir_config,
  +                                                       &expires_module);
  +    notes = (expires_interphase_t *) ap_get_module_config(r->request_config,
  +                                                          &expires_module);
  +
  +    /*
  +     * If this filter is getting called, it *should* mean that
  +     * the fixup-phase handler ran and set things up for us.
  +     * Check to see which output header table we should use;
  +     * mod_cgi loads script fields into r->err_headers_out,
  +     * for instance.
  +     */
  +    bytype_expiry = apr_table_get(r->err_headers_out, "Expires");
  +    if (bytype_expiry != NULL) {
  +        t = r->err_headers_out;
  +    }
  +    else {
  +        bytype_expiry = apr_table_get(r->headers_out, "Expires");
  +        t = r->headers_out;
  +    }
  +    if (bytype_expiry == NULL) {
  +        /*
  +         * No expiration has been set, so we can apply any managed by
  +         * this module.  Check for one for this content type.
  +         */
  +        bytype_expiry = apr_table_get(conf->expiresbytype,
  +                                      ap_field_noparam(r->pool,
  +                                                       r->content_type));
  +        if (bytype_expiry != NULL) {
  +            set_expiration_fields(r, bytype_expiry, t);
  +        }
  +        else if ((notes != NULL) && notes->defaulted) {
  +            /*
  +             * None for this type, but there was a default defined --
  +             * so use it.
  +             */
  +            t = apr_table_overlay(r->pool, notes->expfields, t);
  +        }
  +    }
  +    ap_remove_output_filter(f);
  +    return ap_pass_brigade(f->next, b);
  +}
  +
  +static int add_expires(request_rec *r)
  +{
  +    expires_dir_config *conf;
  +    expires_interphase_t *notes;
  +    apr_table_t *rfields;
  +    char *code;
  +
  +    if (ap_is_HTTP_ERROR(r->status)) {/* Don't add Expires headers to errors */
  +        return DECLINED;
  +    }
  +
  +    if (r->main != NULL) {      /* Say no to subrequests */
  +        return DECLINED;
  +    }
  +
  +    conf = (expires_dir_config *) ap_get_module_config(r->per_dir_config,
  +                                                       &expires_module);
  +    if (conf == NULL) {
  +        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  +                    "internal error: %s", r->filename);
  +        return HTTP_INTERNAL_SERVER_ERROR;
  +    }
  +
  +    if (conf->active != ACTIVE_ON) {
  +        return DECLINED;
  +    }
  +
  +    notes = apr_palloc(r->pool, sizeof(expires_interphase_t));
  +    notes->defaulted = 0;
  +    notes->expfields = apr_table_make(r->pool, 4);
  +    ap_set_module_config(r->request_config, &expires_module, notes);
  +
  +    /*
  +     * If there are any ExpiresByType directives for this scope,
  +     * add the output filter and defer all setting to it.  We
  +     * do make a note of any ExpiresDefault value for its use.
  +     */
  +    if (! apr_is_empty_table(conf->expiresbytype)) {
  +        ap_add_output_filter("EXPIRATION", NULL, r, r->connection);
  +        rfields = notes->expfields;
  +    }
  +    else {
  +        rfields = r->headers_out;
  +    }
  +    /*
  +     * Apply the default expiration if there is one; the filter will
  +     * narrow it down later if possible.
  +     */
  +    code = conf->expiresdefault;
  +
  +    if (code[0] == '\0') {
  +        return OK;
  +    }
  +    else {
  +        /*
  +         * Note that we're setting it from the default, so that
  +         * the output filter (if it runs) knows it can override the
  +         * value.  This allows the by-type filter to be able to
  +         * tell the difference between a value set by, say, a
  +         * CGI script and the one we set by default.
  +         */
  +        notes->defaulted = 1;
  +    }
  +    return set_expiration_fields(r, code, rfields);
  +}
  +
   static void register_hooks(apr_pool_t *p)
   {
  +    ap_register_output_filter("EXPIRATION", expires_by_type_filter, NULL,
  +                              AP_FTYPE_CONTENT_SET);
       ap_hook_fixups(add_expires,NULL,NULL,APR_HOOK_MIDDLE);
   }
   
  
  
  

Mime
View raw message