Mailing List Archive

r832 - trunk/varnish-cache/bin/varnishd
Author: phk
Date: 2006-08-18 21:53:43 +0200 (Fri, 18 Aug 2006)
New Revision: 832

Modified:
trunk/varnish-cache/bin/varnishd/cache.h
trunk/varnish-cache/bin/varnishd/cache_center.c
trunk/varnish-cache/bin/varnishd/cache_http.c
Log:
Do a better job on Connection: header processing in client requests.

Add a flag field for each HTTP header and define a bit HDF_FILTER
to mean "filter this out", and initialize to zero all relevant
places.

If HDF_FILTER is set, do not copy the header across when filtering.

Run through Connection: header (if present) and set HDF_FILTER on
any header that matches a word in the contents.

If we are not HTTP/1.1 and have no Connection header, we close
the session when this reqest is done.

If we have a Connection header, we respect that.




Modified: trunk/varnish-cache/bin/varnishd/cache.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache.h 2006-08-18 19:10:44 UTC (rev 831)
+++ trunk/varnish-cache/bin/varnishd/cache.h 2006-08-18 19:53:43 UTC (rev 832)
@@ -73,6 +73,8 @@
} logtag;

struct http_hdr hd[HTTP_HDR_MAX];
+ unsigned char hdf[HTTP_HDR_MAX];
+#define HDF_FILTER (1 << 0) /* Filtered by Connection */
unsigned nhd;
};

@@ -360,6 +362,7 @@
int http_RecvHead(struct http *hp, int fd);
int http_DissectRequest(struct http *sp, int fd);
int http_DissectResponse(struct http *sp, int fd);
+void http_DoConnection(struct sess *sp);

#define HTTPH(a, b, c, d, e, f, g) extern char b[];
#include "http_headers.h"

Modified: trunk/varnish-cache/bin/varnishd/cache_center.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_center.c 2006-08-18 19:10:44 UTC (rev 831)
+++ trunk/varnish-cache/bin/varnishd/cache_center.c 2006-08-18 19:53:43 UTC (rev 832)
@@ -565,10 +565,7 @@
return (0);
}

- if (http_GetHdr(sp->http, H_Connection, &b) && !strcmp(b, "close"))
- sp->doclose = "Connection:";
- else if (strcmp(sp->http->hd[HTTP_HDR_PROTO].b, "HTTP/1.1"))
- sp->doclose = "not HTTP/1.1";
+ http_DoConnection(sp);

sp->backend = sp->vcl->backend[0];


Modified: trunk/varnish-cache/bin/varnishd/cache_http.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_http.c 2006-08-18 19:10:44 UTC (rev 831)
+++ trunk/varnish-cache/bin/varnishd/cache_http.c 2006-08-18 19:53:43 UTC (rev 832)
@@ -99,35 +99,47 @@

/*--------------------------------------------------------------------*/

-int
-http_GetHdr(struct http *hp, const char *hdr, char **ptr)
+static unsigned
+http_findhdr(struct http *hp, unsigned l, const char *hdr)
{
- unsigned u, l;
- char *p;
+ unsigned u;

- l = hdr[0];
- assert(l == strlen(hdr + 1));
- assert(hdr[l] == ':');
- hdr++;
for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
assert(hp->hd[u].b != NULL);
assert(hp->hd[u].e != NULL);
- if (hp->hd[u].e < hp->hd[u].b + l)
+ if (hp->hd[u].e < hp->hd[u].b + l + 1)
continue;
- if (hp->hd[u].b[l-1] != ':')
+ if (hp->hd[u].b[l] != ':')
continue;
if (strncasecmp(hdr, hp->hd[u].b, l))
continue;
- p = hp->hd[u].b + l;
- while (isspace(*p))
- p++;
- *ptr = p;
- return (1);
+ return (u);
}
- *ptr = NULL;
return (0);
}

+int
+http_GetHdr(struct http *hp, const char *hdr, char **ptr)
+{
+ unsigned u, l;
+ char *p;
+
+ l = hdr[0];
+ assert(l == strlen(hdr + 1));
+ assert(hdr[l] == ':');
+ hdr++;
+ u = http_findhdr(hp, l - 1, hdr);
+ if (u == 0) {
+ *ptr = NULL;
+ return (0);
+ }
+ p = hp->hd[u].b + l;
+ while (isspace(*p))
+ p++;
+ *ptr = p;
+ return (1);
+}
+
/*--------------------------------------------------------------------*/

int
@@ -165,6 +177,43 @@

/*--------------------------------------------------------------------*/

+void
+http_DoConnection(struct sess *sp)
+{
+ struct http *hp = sp->http;
+ char *p, *q;
+ int i;
+ unsigned u;
+
+ if (!http_GetHdr(hp, H_Connection, &p)) {
+ if (strcmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.1"))
+ sp->doclose = "not HTTP/1.1";
+ return;
+ }
+ VSL(SLT_Debug, sp->fd, "DoConnect(%s)", p);
+ for (; *p; p++) {
+ if (isspace(*p))
+ continue;
+ if (*p == ',')
+ continue;
+ for (q = p + 1; *q; q++)
+ if (*q == ',' || isspace(*q))
+ break;
+ i = q - p;
+ if (i == 5 && !strncasecmp(p, "close", i))
+ sp->doclose = "Connection: close";
+ u = http_findhdr(hp, i, p);
+ if (u != 0)
+ hp->hdf[u] |= HDF_FILTER;
+ VSL(SLT_Debug, sp->fd, "FLD(%.*s) u = %u", q - p, p, u);
+ if (!*q)
+ break;
+ p = q;
+ }
+}
+
+/*--------------------------------------------------------------------*/
+
int
http_HdrIs(struct http *hp, const char *hdr, const char *val)
{
@@ -275,6 +324,7 @@
hp->conds = 1;

if (hp->nhd < HTTP_HDR_MAX) {
+ hp->hdf[hp->nhd] = 0;
hp->hd[hp->nhd].b = p;
hp->hd[hp->nhd].e = q;
VSLH(HTTP_T_Header, fd, hp, hp->nhd);
@@ -577,6 +627,7 @@
assert(fm != NULL);
to->hd[n].b = (void*)(uintptr_t)fm;
to->hd[n].e = (void*)(uintptr_t)strchr(fm, '\0');
+ to->hdf[n] = 0;
VSLH(tag, fd, to, n);
}

@@ -588,6 +639,7 @@
assert(fm->hd[n].b != NULL);
to->hd[n].b = fm->hd[n].b;
to->hd[n].e = fm->hd[n].e;
+ to->hdf[n] = fm->hdf[n];
VSLH(tag, fd, to, n);
}

@@ -664,6 +716,8 @@
CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
to->nhd = HTTP_HDR_FIRST;
for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
+ if (fm->hdf[u] & HDF_FILTER)
+ continue;
#define HTTPH(a, b, c, d, e, f, g) \
if (((e) & how) && http_IsHdr(&fm->hd[u], (b))) \
continue;