From 3ecf0bc005da7aaeee2d37a428e5d6ab06f6c138 Mon Sep 17 00:00:00 2001 From: phk Date: Thu, 20 Jul 2006 09:29:45 +0000 Subject: [PATCH] Implement "If-Modified-Since" conditional queries git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@513 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/cache.h | 6 +- varnish-cache/bin/varnishd/cache_fetch.c | 4 ++ varnish-cache/bin/varnishd/cache_http.c | 11 +++- varnish-cache/bin/varnishd/cache_response.c | 63 ++++++++++++++++++++- 4 files changed, 80 insertions(+), 4 deletions(-) diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index e759968f..f3b14071 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -56,6 +56,8 @@ struct http { char *proto; char *status; char *response; + + unsigned conds; /* If-* headers present */ unsigned nhdr; char **hdr; @@ -151,6 +153,8 @@ struct object { time_t entered; time_t ttl; + time_t last_modified; + char *header; TAILQ_ENTRY(object) list; @@ -337,7 +341,7 @@ void VSL(enum shmlogtag tag, unsigned id, const char *fmt, ...); /* cache_response.c */ void RES_Error(struct sess *sp, int error, const char *msg); void RES_Flush(struct sess *sp); -void RES_Write(struct sess *sp, void *ptr, size_t len); +void RES_Write(struct sess *sp, const void *ptr, size_t len); void RES_WriteObj(struct sess *sp); /* cache_vcl.c */ diff --git a/varnish-cache/bin/varnishd/cache_fetch.c b/varnish-cache/bin/varnishd/cache_fetch.c index ba8ed484..a052a358 100644 --- a/varnish-cache/bin/varnishd/cache_fetch.c +++ b/varnish-cache/bin/varnishd/cache_fetch.c @@ -12,8 +12,10 @@ #include #include #include +#include #include "shmlog.h" +#include "libvarnish.h" #include "cache.h" /* @@ -211,6 +213,8 @@ FetchBody(struct worker *w, struct sess *sp) vc = sp->vbc; hp = sp->bkd_http; + if (http_GetHdr(hp, "Last-Modified", &b)) + sp->obj->last_modified = TIM_parse(b); http_BuildSbuf(sp->fd, Build_Reply, w->sb, hp); if (body) { if (http_GetHdr(hp, "Content-Length", &b)) diff --git a/varnish-cache/bin/varnishd/cache_http.c b/varnish-cache/bin/varnishd/cache_http.c index 483d04f8..dc1dd829 100644 --- a/varnish-cache/bin/varnishd/cache_http.c +++ b/varnish-cache/bin/varnishd/cache_http.c @@ -156,7 +156,10 @@ http_GetStatus(struct http *hp) return (strtoul(hp->status, NULL /* XXX */, 10)); } -/*--------------------------------------------------------------------*/ +/*-------------------------------------------------------------------- + * Dissect the headers of the HTTP protocol message. + * Detect conditionals (headers which start with '^[Ii][Ff]-') + */ static int http_dissect_hdrs(struct http *hp, int fd, char *p) @@ -167,6 +170,7 @@ http_dissect_hdrs(struct http *hp, int fd, char *p) p++; hp->nhdr = 0; + hp->conds = 0; r = NULL; /* For FlexeLint */ assert(p < hp->v); /* http_header_complete() guarantees this */ for (; p < hp->v; p = r) { @@ -179,6 +183,11 @@ http_dissect_hdrs(struct http *hp, int fd, char *p) if (p == q) break; + if ((p[0] == 'i' || p[0] == 'I') && + (p[1] == 'f' || p[1] == 'F') && + p[2] == '-') + hp->conds = 1; + if (hp->nhdr < heritage.mem_http_headers) { hp->hdr[hp->nhdr++] = p; VSLR(SLT_Header, fd, p, q); diff --git a/varnish-cache/bin/varnishd/cache_response.c b/varnish-cache/bin/varnishd/cache_response.c index 4fb384be..4290007c 100644 --- a/varnish-cache/bin/varnishd/cache_response.c +++ b/varnish-cache/bin/varnishd/cache_response.c @@ -93,20 +93,76 @@ RES_Flush(struct sess *sp) } void -RES_Write(struct sess *sp, void *ptr, size_t len) +RES_Write(struct sess *sp, const void *ptr, size_t len) { if (sp->fd < 0 || len == 0) return; + if (len == -1) + len = strlen(ptr); if (sp->wrk->niov == MAX_IOVS) RES_Flush(sp); if (sp->fd < 0) return; - sp->wrk->iov[sp->wrk->niov].iov_base = ptr; + sp->wrk->iov[sp->wrk->niov].iov_base = (void*)(uintptr_t)ptr; sp->wrk->iov[sp->wrk->niov++].iov_len = len; sp->wrk->liov += len; } +/*--------------------------------------------------------------------*/ + +static void +res_do_304(struct sess *sp, char *p) +{ + struct sbuf *sb; + + sb = sp->wrk->sb; + sbuf_clear(sb); + + VSL(SLT_Status, sp->fd, "%u", 304); + VSL(SLT_Length, sp->fd, "%u", 0); + RES_Write(sp, "HTTP/1.1 304 Not Modified\r\n", -1); + RES_Write(sp, "Via: 1.1 varnish\r\n", -1); + RES_Write(sp, "Last-Modified: ", -1); + RES_Write(sp, p, -1); + RES_Write(sp, "\r\n", -1); + if (strcmp(sp->http->proto, "HTTP/1.1")) + RES_Write(sp, "Connection: close\r\n", -1); + sbuf_printf(sb, "X-Varnish: xid %u\r\n", sp->obj->xid); + sbuf_printf(sb, "\r\n"); + sbuf_finish(sb); + RES_Write(sp, sbuf_data(sb), sbuf_len(sb)); + RES_Flush(sp); +} + +/*--------------------------------------------------------------------*/ + +static int +res_do_conds(struct sess *sp) +{ + char *p; + time_t ims; + + if (sp->obj->last_modified > 0 && + http_GetHdr(sp->http, "If-Modified-Since", &p)) { + ims = TIM_parse(p); + if (ims > sp->t_req) /* [RFC2616 14.25] */ + return (0); + if (ims > sp->obj->last_modified) { + VSL(SLT_Debug, sp->fd, + "Cond: %d > %d ", sp->obj->last_modified, ims); + return (0); + } + VSL(SLT_Debug, sp->fd, + "Cond: %d <= %d", sp->obj->last_modified, ims); + res_do_304(sp, p); + return (1); + } + return (0); +} + +/*--------------------------------------------------------------------*/ + void RES_WriteObj(struct sess *sp) { @@ -118,6 +174,9 @@ RES_WriteObj(struct sess *sp) sb = sp->wrk->sb; + if (sp->obj->response == 200 && sp->http->conds && res_do_conds(sp)) + return; + VSL(SLT_Status, sp->fd, "%u", sp->obj->response); VSL(SLT_Length, sp->fd, "%u", sp->obj->len); -- 2.39.5