summaryrefslogtreecommitdiff
path: root/src/mod_expire.c
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2016-10-20 10:11:54 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2016-10-20 10:48:06 -0400
commit9f93454d56de42261bf6f67ecd4727c14d5e8946 (patch)
tree1783b968fd5a7a782eab6da304985cd514735d90 /src/mod_expire.c
parent1f3ad401ba4d7f75f554eaf4defd8ad19582f96c (diff)
downloadlighttpd-git-9f93454d56de42261bf6f67ecd4727c14d5e8946.tar.gz
[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
Diffstat (limited to 'src/mod_expire.c')
-rw-r--r--src/mod_expire.c77
1 files changed, 71 insertions, 6 deletions
diff --git a/src/mod_expire.c b/src/mod_expire.c
index 22a875cf..460aeee1 100644
--- a/src/mod_expire.c
+++ b/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;