Navigation Menu

Skip to content

Commit

Permalink
Expiration headers returned by Front-Line Cache can now be overwritten.
Browse files Browse the repository at this point in the history
git-svn-id: svn://cherokee-project.com/cherokee/trunk@6620 5dc97367-97f1-0310-9951-d761b3857238
  • Loading branch information
alobbs committed May 14, 2011
1 parent 8e0652c commit d7c81af
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 59 deletions.
82 changes: 44 additions & 38 deletions cherokee/connection.c
Expand Up @@ -616,16 +616,29 @@ build_response_header_authentication (cherokee_connection_t *conn, cherokee_buff
}


ret_t
cherokee_connection_read_post (cherokee_connection_t *conn)
{
/* Shortcut
*/
if (conn->handler->read_post == NULL) {
return ret_ok;
}

return cherokee_handler_read_post (conn->handler);
}


void
cherokee_connection_add_expiration_header (cherokee_connection_t *conn,
cherokee_buffer_t *buffer,
cherokee_boolean_t use_maxage)
{
time_t exp_time;
struct tm exp_tm;
char bufstr[DTM_SIZE_GMTTM_STR + 2];
size_t szlen = 0;
cherokee_boolean_t first_prop = true;
time_t exp_time;
struct tm exp_tm;
char bufstr[DTM_SIZE_GMTTM_STR + 2];
size_t szlen = 0;
cherokee_boolean_t first_prop = true;

/* Expires, and Cache-Control: max-age
*/
Expand Down Expand Up @@ -801,22 +814,6 @@ build_response_header (cherokee_connection_t *conn,
}
}

/* Expiration
*/
if (conn->expiration != cherokee_expiration_none) {
/* Front-line Cache (in) */
if (conn->flcache.mode == flcache_mode_in) {
cherokee_buffer_clean (tmp1);
cherokee_connection_add_expiration_header (conn, tmp1, false);
cherokee_buffer_add_buffer (buffer, tmp1);
cherokee_buffer_add_buffer (&conn->flcache.header, tmp1);
}
/* Straight */
else {
cherokee_connection_add_expiration_header (conn, buffer, true);
}
}

/* Redirected connections
*/
if (conn->redirect.len >= 1) {
Expand All @@ -840,25 +837,36 @@ build_response_header (cherokee_connection_t *conn,
cherokee_encoder_add_headers (conn->encoder, buffer);
}
}

/* Headers ops
*/
if (conn->header_ops) {
cherokee_header_op_render (conn->header_ops, buffer);
}
}


ret_t
cherokee_connection_read_post (cherokee_connection_t *conn)
static void
build_response_header_final (cherokee_connection_t *conn,
cherokee_buffer_t *buffer)
{
/* Shortcut
cherokee_buffer_t *tmp1 = THREAD_TMP_BUF1(CONN_THREAD(conn));

/* Expiration
*/
if (conn->handler->read_post == NULL) {
return ret_ok;
if (conn->expiration != cherokee_expiration_none) {
/* Add expiration headers if Front-Line Cache is not
* enabled. If it were, the header was already stored
* in the response file.
*/
if (conn->flcache.mode == flcache_mode_undef) {
cherokee_connection_add_expiration_header (conn, buffer, true);
} else if (conn->flcache.mode == flcache_mode_in) {
cherokee_header_del_entry (buffer, "Cache-Control", 13);
cherokee_connection_add_expiration_header (conn, buffer, true);
}
}

return cherokee_handler_read_post (conn->handler);
/* Headers ops:
* This must be the last operation
*/
if (conn->header_ops) {
cherokee_header_op_render (conn->header_ops, &conn->buffer);
}
}


Expand Down Expand Up @@ -944,19 +952,17 @@ cherokee_connection_build_header (cherokee_connection_t *conn)
}

out:
/* Add the server headers
/* Add the server headers (phase 1)
*/
build_response_header (conn, &conn->buffer);

/* Add handler headers
*/
cherokee_buffer_add_buffer (&conn->buffer, &conn->header_buffer);

/* Headers ops
/* Add the server headers (phase 2)
*/
if (conn->header_ops) {
cherokee_header_op_render (conn->header_ops, &conn->buffer);
}
build_response_header_final (conn, &conn->buffer);

/* EOH
*/
Expand Down
58 changes: 42 additions & 16 deletions cherokee/flcache.c
Expand Up @@ -340,7 +340,7 @@ cherokee_flcache_conn_init (cherokee_flcache_conn_t *flcache_conn)
flcache_conn->header_sent = 0;
flcache_conn->response_sent = 0;
flcache_conn->avl_node_ref = NULL;
flcache_conn->mode = flcache_mdoe_undef;
flcache_conn->mode = flcache_mode_undef;
flcache_conn->fd = -1;

cherokee_buffer_init (&flcache_conn->header);
Expand Down Expand Up @@ -407,14 +407,17 @@ inspect_header (cherokee_flcache_conn_t *flcache_conn,
const char *header_end;
char chr_end;
char *p, *q;
cherokee_avl_flcache_node_t *node = flcache_conn->avl_node_ref;
cherokee_boolean_t via_found = false;
cherokee_buffer_t *tmp = THREAD_TMP_BUF2(CONN_THREAD(conn));
cherokee_boolean_t do_cache = false;
cherokee_boolean_t overwrite_control;
cherokee_avl_flcache_node_t *node = flcache_conn->avl_node_ref;
cherokee_boolean_t via_found = false;
cherokee_buffer_t *tmp = THREAD_TMP_BUF2(CONN_THREAD(conn));
cherokee_boolean_t do_cache = false;

begin = header->buf;
header_end = header->buf + header->len;

overwrite_control = (conn->expiration != cherokee_expiration_none);

while ((begin < header_end)) {
end = cherokee_header_get_next_line (begin);
if (end == NULL) {
Expand All @@ -427,10 +430,16 @@ inspect_header (cherokee_flcache_conn_t *flcache_conn,
/* Expire
*/
if (strncasecmp (begin, "Expires:", 8) == 0) {
/* Cache control overridden */
if (overwrite_control) {
goto remove_line;
}

/* Regular Cache control */
value = begin + 8;
while ((*value == ' ') && (value < end)) value++;

node->valid_until = 0;
node->valid_until = 0;
cherokee_dtm_str2time (value, end - value, &node->valid_until);

if (node->valid_until > cherokee_bogonow_now + 1) {
Expand All @@ -441,20 +450,19 @@ inspect_header (cherokee_flcache_conn_t *flcache_conn,
/* Content-length
*/
else if (strncasecmp (begin, "Content-Length:", 15) == 0) {
*end = chr_end;

while ((*end == CHR_CR) || (*end == CHR_LF))
end++;

cherokee_buffer_remove_chunk (header, begin - header->buf, end - begin);

end = begin;
continue;
goto remove_line;
}

/* Cache-Control
*/
else if (strncasecmp (begin, "Cache-Control:", 14) == 0) {

/* Cache control overridden */
if (overwrite_control) {
goto remove_line;
}

/* Regular Cache control */
value = begin + 8;
while ((*value == ' ') && (value < end)) value++;

Expand Down Expand Up @@ -560,6 +568,18 @@ inspect_header (cherokee_flcache_conn_t *flcache_conn,
while ((*end == CHR_CR) || (*end == CHR_LF))
end++;
begin = end;
continue;

remove_line:
*end = chr_end;

while ((*end == CHR_CR) || (*end == CHR_LF))
end++;

cherokee_buffer_remove_chunk (header, begin - header->buf, end - begin);

end = begin;
continue;
}

/* Check the caching policy
Expand All @@ -578,6 +598,12 @@ inspect_header (cherokee_flcache_conn_t *flcache_conn,
cherokee_buffer_add_str (header, " (Cherokee/"PACKAGE_VERSION")" CRLF);
}

/* Overwritten Cache-Control / Expiration
*/
if (overwrite_control) {
cherokee_connection_add_expiration_header (conn, header, false);
}

return ret_ok;
}

Expand Down Expand Up @@ -858,7 +884,7 @@ cherokee_flcache_conn_clean (cherokee_flcache_conn_t *flcache_conn)
*/
flcache_conn->header_sent = 0;
flcache_conn->response_sent = 0;
flcache_conn->mode = flcache_mdoe_undef;
flcache_conn->mode = flcache_mode_undef;

if (flcache_conn->fd != -1) {
cherokee_fd_close (flcache_conn->fd);
Expand Down
2 changes: 1 addition & 1 deletion cherokee/flcache.h
Expand Up @@ -46,7 +46,7 @@ typedef struct cherokee_flcache_conn cherokee_flcache_conn_t;
*/

typedef enum {
flcache_mdoe_undef,
flcache_mode_undef,
flcache_mode_in,
flcache_mode_out,
flcache_mode_error
Expand Down
4 changes: 2 additions & 2 deletions cherokee/handler_file.c
Expand Up @@ -484,7 +484,7 @@ cherokee_handler_file_custom_init (cherokee_handler_file_t *fhdl,
(conn->encoder_new_func == NULL) &&
(HDL_FILE_PROP(fhdl)->use_cache) &&
(conn->socket.is_tls == non_TLS) &&
(conn->flcache.mode == flcache_mdoe_undef) &&
(conn->flcache.mode == flcache_mode_undef) &&
(http_method_with_body (conn->header.method)) &&
(fhdl->info->st_size <= srv->iocache->max_file_size) &&
(fhdl->info->st_size >= srv->iocache->min_file_size));
Expand Down Expand Up @@ -624,7 +624,7 @@ cherokee_handler_file_custom_init (cherokee_handler_file_t *fhdl,
(conn->encoder == NULL) &&
(conn->encoder_new_func == NULL) &&
(conn->socket.is_tls == non_TLS) &&
(conn->flcache.mode == flcache_mdoe_undef) &&
(conn->flcache.mode == flcache_mode_undef) &&
(fhdl->info->st_size >= srv->sendfile.min) &&
(fhdl->info->st_size < srv->sendfile.max));

Expand Down
36 changes: 36 additions & 0 deletions cherokee/util.c
Expand Up @@ -2033,6 +2033,42 @@ cherokee_header_get_next_line (char *string)
return end1;
}

ret_t
cherokee_header_del_entry (cherokee_buffer_t *header,
const char *header_name,
int header_name_len)
{
char *end;
char *begin;
const char *header_end;

begin = header->buf;
header_end = header->buf + header->len;

while ((begin < header_end)) {
end = cherokee_header_get_next_line (begin);
if (end == NULL) {
break;
}

/* Is it the header? */
if (strncasecmp (begin, header_name, header_name_len) == 0) {
while ((*end == CHR_CR) || (*end == CHR_LF))
end++;

cherokee_buffer_remove_chunk (header, begin - header->buf, end - begin);
return ret_ok;
}

/* Next line */
while ((*end == CHR_CR) || (*end == CHR_LF))
end++;
begin = end;
}

return ret_not_found;
}


#ifndef HAVE_STRNSTR
char *
Expand Down
6 changes: 5 additions & 1 deletion cherokee/util.h
Expand Up @@ -227,7 +227,11 @@ ret_t cherokee_split_arguments (cherokee_buffer_t *request,
ret_t cherokee_parse_query_string (cherokee_buffer_t *qstring,
cherokee_avl_t *arguments);

char *cherokee_header_get_next_line (char *line);
char *cherokee_header_get_next_line (char *line);
ret_t cherokee_header_del_entry (cherokee_buffer_t *header,
const char *header_name,
int header_name_len);


CHEROKEE_END_DECLS

Expand Down
56 changes: 56 additions & 0 deletions qa/285-Flcache-overwrite.py
@@ -0,0 +1,56 @@
from base import *

DIR = "flcache-replace1"
FILE = "file.txt"
CONTENT = "Front-line cache boosts Cherokee performance"

CONF = """
vserver!1!rule!2850!match = directory
vserver!1!rule!2850!match!directory = /%(DIR)s
vserver!1!rule!2850!flcache = allow
vserver!1!rule!2850!flcache!policy = all_but_forbidden
vserver!1!rule!2850!expiration = time
vserver!1!rule!2850!expiration!caching = public
vserver!1!rule!2850!expiration!time = 300
vserver!1!rule!2850!handler = cgi
""" %(globals())

CGI_CODE = """#!/bin/sh
echo "Content-Type: text/plain"
echo "Cache-Control: no-store, no-cache"
echo
echo "%(CONTENT)s"
""" %(globals())


class TestEntry (TestBase):
def __init__ (self):
TestBase.__init__ (self, __file__)
self.request = "GET /%s/%s HTTP/1.0\r\n" %(DIR, FILE) +\
"Connection: close\r\n"
self.expected_error = 200


class Test (TestCollection):
def __init__ (self):
TestCollection.__init__ (self, __file__)

self.name = "Front-line: Overwrite Cache-Control"
self.conf = CONF
self.proxy_suitable = True

def Prepare (self, www):
d = self.Mkdir (www, DIR)
self.WriteFile (d, FILE, 0755, CGI_CODE)

# First request
obj = self.Add (TestEntry())
obj.expected_content = ['X-Cache: MISS', CONTENT, "public"]
obj.forbidden_content = ['no-store', 'no-cache']

# Second request
obj = self.Add (TestEntry())
obj.expected_content = ['X-Cache: HIT', CONTENT, "public"]
obj.forbidden_content = ['no-store', 'no-cache']
3 changes: 2 additions & 1 deletion qa/Makefile.am
Expand Up @@ -305,7 +305,8 @@ run-tests.py \
281-Flcache-expired1.py \
282-Flcache-expired2.py \
283-Flcache-expired3.py \
284-SSI-include-recursive.py
284-SSI-include-recursive.py \
285-Flcache-overwrite.py

test:
python -m compileall .
Expand Down

0 comments on commit d7c81af

Please sign in to comment.