r832 - trunk/varnish-cache/bin/varnishd

phk at projects.linpro.no phk at projects.linpro.no
Fri Aug 18 21:53:43 CEST 2006


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;




More information about the varnish-commit mailing list