Bug #1386

mod_expire overwrites existing Cache-Control headers

Added by jrabbit over 12 years ago. Updated over 3 years ago.

Target version:
Start date:
Due date:
% Done:


Estimated time:
Missing in 1.5.x:


When you use mod_expire to set the Expires header, it also writes a Cache-Control header with a max-age attribute. However, that replaces any more detailed Cache-Control header created with mod_setenv. It doesn't seem to matter which module is loaded first - mod_expires still trumps mod_setenv.

Example Configuration:

$HTTP["url"] =~ "\.css$" {
        setenv.add-response-header = ( "Cache-Control" => "public, max-age=172000, post-check=172000, pre-check=172000" )
        expire.url = ( "" => "access 172000 seconds" )

This appears to be because mod_expire uses response_header_overwrite where as mod_setenv uses response_header_insert. However, I'm not sure which is the best fix:

a) Change mod_expire to only insert the header if its missing rather than overwrite it.

b) Change mod_setenv to overwrite headers rather than inserting them.

It depends if mod_setenv not overwriting existing headers should be considered a bug - if so then option b, else option a.


Updated by bonsaikitten over 11 years ago

--- lighttpd-orig/lighttpd-1.4.20/src/mod_expire.c      2008-07-30 21:38:32.000000000 +0200
+++ lighttpd-1.4.20/src/mod_expire.c    2008-11-12 11:41:03.000000000 +0100
@@ -17,6 +17,7 @@
  * set 'Expires:' HTTP Headers on demand

+#define response_header_exists(con, key) (NULL != array_get_element(con->response.headers, key))

 /* plugin config for all request/connections */
@@ -342,7 +343,9 @@
                        buffer_copy_string_len(p->expire_tstmp, CONST_STR_LEN("max-age="));
                        buffer_append_long(p->expire_tstmp, ts);

-                       response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp));
+                       if (!response_header_exists(con, "Cache-Control")) {
+                         response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp));
+                       }

                        return HANDLER_GO_ON;

This patch fixes the issue for me. It now only overwrites the Cache-Control header if not set by anything else (like mod_setenv )
This behaviour is also more intuitive as it honours the settings from the config file and doesn't magically overwrite them.


Updated by gstrauss almost 4 years ago

  • Description updated (diff)
  • Assignee deleted (jan)
  • Missing in 1.5.x set to Yes

FYI: fixed in lighttpd 1.4.x in #1997 and #2068


Updated by gstrauss almost 4 years ago

  • Category changed from mod_setenv to mod_expire

Updated by gstrauss over 3 years ago

  • Status changed from New to Obsolete

Also available in: Atom