Browse Source

[mod_expire] expire by mimetype (fixes #423)

new directive expire.mimetypes for list of mimetypes and expirations

mod_expire is now processed at the start of the response, and so now
may be applied to all responses, including dynamic responses.

mod_expire now applies only to GET and HEAD requests where the response
status is 200 OK or 206 Partial Content, and for which no other modules
or backend has already added a Cache-Control response header.

expire.url takes precedence over expire.mimetypes

x-ref:
  "Add expire by Mimetype"
  https://redmine.lighttpd.net/issues/423
personal/stbuehler/mod-csrf
Glenn Strauss 5 years ago
parent
commit
9f93454d56
  1. 77
      src/mod_expire.c

77
src/mod_expire.c

@ -25,6 +25,7 @@
typedef struct {
array *expire_url;
array *expire_mimetypes;
} plugin_config;
typedef struct {
@ -68,6 +69,7 @@ FREE_FUNC(mod_expire_free) {
if (NULL == s) continue;
array_free(s->expire_url);
array_free(s->expire_mimetypes);
free(s);
}
free(p->config_storage);
@ -219,6 +221,7 @@ SETDEFAULTS_FUNC(mod_expire_set_defaults) {
config_values_t cv[] = {
{ "expire.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
{ "expire.mimetypes", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
};
@ -232,8 +235,10 @@ SETDEFAULTS_FUNC(mod_expire_set_defaults) {
s = calloc(1, sizeof(plugin_config));
s->expire_url = array_init();
s->expire_mimetypes = array_init();
cv[0].destination = s->expire_url;
cv[1].destination = s->expire_mimetypes;
p->config_storage[i] = s;
@ -251,6 +256,17 @@ SETDEFAULTS_FUNC(mod_expire_set_defaults) {
return HANDLER_ERROR;
}
}
for (k = 0; k < s->expire_mimetypes->used; k++) {
data_string *ds = (data_string *)s->expire_mimetypes->data[k];
/* parse lines */
if (-1 == mod_expire_get_offset(srv, p, ds->value, NULL)) {
log_error_write(srv, __FILE__, __LINE__, "sb",
"parsing expire.mimetypes failed:", ds->value);
return HANDLER_ERROR;
}
}
}
@ -264,6 +280,7 @@ static int mod_expire_patch_connection(server *srv, connection *con, plugin_data
plugin_config *s = p->config_storage[0];
PATCH(expire_url);
PATCH(expire_mimetypes);
/* skip the first, the global context */
for (i = 1; i < srv->config_context->used; i++) {
@ -279,6 +296,8 @@ static int mod_expire_patch_connection(server *srv, connection *con, plugin_data
if (buffer_is_equal_string(du->key, CONST_STR_LEN("expire.url"))) {
PATCH(expire_url);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("expire.mimetypes"))) {
PATCH(expire_mimetypes);
}
}
}
@ -287,25 +306,72 @@ static int mod_expire_patch_connection(server *srv, connection *con, plugin_data
}
#undef PATCH
URIHANDLER_FUNC(mod_expire_path_handler) {
CONNECTION_FUNC(mod_expire_handler) {
plugin_data *p = p_d;
int s_len;
data_string *ds = NULL;
size_t s_len;
size_t k;
/* Add caching headers only to http_status 200 OK or 206 Partial Content */
if (con->http_status != 200 && con->http_status != 206) return HANDLER_GO_ON;
/* Add caching headers only to GET or HEAD requests */
if ( con->request.http_method != HTTP_METHOD_GET
&& con->request.http_method != HTTP_METHOD_HEAD) return HANDLER_GO_ON;
/* Add caching headers only if not already present */
ds = (data_string *)array_get_element(con->response.headers, "Cache-Control");
if (NULL != ds && !buffer_string_is_empty(ds->value)) return HANDLER_GO_ON;
if (buffer_is_empty(con->uri.path)) return HANDLER_GO_ON;
mod_expire_patch_connection(srv, con, p);
s_len = buffer_string_length(con->uri.path);
/* check expire.url */
for (k = 0; k < p->conf.expire_url->used; k++) {
data_string *ds = (data_string *)p->conf.expire_url->data[k];
int ct_len = buffer_string_length(ds->key);
size_t ct_len;
ds = (data_string *)p->conf.expire_url->data[k];
ct_len = buffer_string_length(ds->key);
if (ct_len > s_len) continue;
if (buffer_is_empty(ds->key)) continue;
if (0 == strncmp(con->uri.path->ptr, ds->key->ptr, ct_len)) {
break;
}
}
/* check expire.mimetypes (if no match with expire.url) */
if (k == p->conf.expire_url->used) {
const char *mimetype;
ds = (data_string *)array_get_element(con->response.headers, "Content-Type");
if (NULL != ds && !buffer_string_is_empty(ds->value)) {
mimetype = ds->value->ptr;
s_len = buffer_string_length(ds->value);
} else {
mimetype = "";
s_len = 0;
}
for (k = 0; k < p->conf.expire_mimetypes->used; k++) {
size_t ct_len;
ds = (data_string *)p->conf.expire_mimetypes->data[k];
ct_len = buffer_string_length(ds->key);
if (ct_len > s_len) continue;
if (buffer_is_empty(ds->key)) continue;
/*(omit trailing '*', if present, from prefix match)*/
if (ds->key->ptr[ct_len-1] == '*') --ct_len;
if (0 == strncmp(mimetype, ds->key->ptr, ct_len)) {
break;
}
}
if (k == p->conf.expire_mimetypes->used) {
ds = NULL;
}
}
if (NULL != ds) {
time_t ts, expires;
stat_cache_entry *sce = NULL;
@ -348,7 +414,6 @@ URIHANDLER_FUNC(mod_expire_path_handler) {
response_header_append(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp));
return HANDLER_GO_ON;
}
}
/* not found */
@ -363,7 +428,7 @@ int mod_expire_plugin_init(plugin *p) {
p->name = buffer_init_string("expire");
p->init = mod_expire_init;
p->handle_subrequest_start = mod_expire_path_handler;
p->handle_response_start = mod_expire_handler;
p->set_defaults = mod_expire_set_defaults;
p->cleanup = mod_expire_free;

Loading…
Cancel
Save