Commit a4a89117 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Implement "If-Modified-Since" conditional queries


git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@513 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 3b5b2c6e
......@@ -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 */
......
......@@ -12,8 +12,10 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <time.h>
#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))
......
......@@ -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);
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment