r5666 - in trunk/varnish-cache: bin/varnishd bin/varnishtest/tests lib/libvcl

phk at varnish-cache.org phk at varnish-cache.org
Thu Dec 30 14:14:22 CET 2010


Author: phk
Date: 2010-12-30 14:14:21 +0100 (Thu, 30 Dec 2010)
New Revision: 5666

Added:
   trunk/varnish-cache/bin/varnishtest/tests/g00000.vtc
Modified:
   trunk/varnish-cache/bin/varnishd/cache.h
   trunk/varnish-cache/bin/varnishd/cache_http.c
   trunk/varnish-cache/bin/varnishd/cache_vrt_var.c
   trunk/varnish-cache/bin/varnishd/rfc2616.c
   trunk/varnish-cache/lib/libvcl/generate.py
Log:
Add the "req.can_gzip" VCL variable, which tells if we can send gzip
to the client or not.



Modified: trunk/varnish-cache/bin/varnishd/cache.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache.h	2010-12-28 14:43:15 UTC (rev 5665)
+++ trunk/varnish-cache/bin/varnishd/cache.h	2010-12-30 13:14:21 UTC (rev 5666)
@@ -611,8 +611,11 @@
 void http_ForceGet(const struct http *to);
 void http_Setup(struct http *ht, struct ws *ws);
 int http_GetHdr(const struct http *hp, const char *hdr, char **ptr);
+int http_GetHdrData(const struct http *hp, const char *hdr,
+    const char *field, char **ptr);
 int http_GetHdrField(const struct http *hp, const char *hdr,
     const char *field, char **ptr);
+double http_GetHdrQ(const struct http *hp, const char *hdr, const char *field);
 int http_GetStatus(const struct http *hp);
 const char *http_GetReq(const struct http *hp);
 int http_HdrIs(const struct http *hp, const char *hdr, const char *val);
@@ -776,6 +779,7 @@
 /* rfc2616.c */
 double RFC2616_Ttl(const struct sess *sp);
 enum body_status RFC2616_Body(const struct sess *sp);
+unsigned RFC2616_Req_Gzip(const struct sess *sp);
 
 /* storage_synth.c */
 struct vsb *SMS_Makesynth(struct object *obj);

Modified: trunk/varnish-cache/bin/varnishd/cache_http.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_http.c	2010-12-28 14:43:15 UTC (rev 5665)
+++ trunk/varnish-cache/bin/varnishd/cache_http.c	2010-12-30 13:14:21 UTC (rev 5666)
@@ -290,12 +290,12 @@
 
 
 /*--------------------------------------------------------------------
- * Find a given headerfield, and if present and wanted, the beginning
- * of its value.
+ * Find a given data element in a header according to RFC2616's #rule
+ * (section 2.1, p15)
  */
 
 int
-http_GetHdrField(const struct http *hp, const char *hdr,
+http_GetHdrData(const struct http *hp, const char *hdr,
     const char *field, char **ptr)
 {
 	char *h, *e;
@@ -309,37 +309,113 @@
 	e = strchr(h, '\0');
 	fl = strlen(field);
 	while (h + fl <= e) {
-		/* Skip leading separators */
-		if (vct_issepctl(*h)) {
+		/* Skip leading whitespace and commas */
+		if (vct_islws(*h) || *h == ',') {
 			h++;
 			continue;
 		}
 		/* Check for substrings before memcmp() */
 		if ((h + fl == e || vct_issepctl(h[fl])) &&
 		    !memcmp(h, field, fl)) {
-			/* got it */
-			h += fl;
 			if (ptr != NULL) {
-				/* Skip whitespace, looking for '=' */
-				while (*h && vct_issp(*h))
+				h += fl;
+				while (vct_islws(*h))
 					h++;
-				if (*h == '=') {
-					h++;
-					while (*h && vct_issp(*h))
-						h++;
-					*ptr = h;
-				}
+				*ptr = h;
 			}
 			return (1);
 		}
-		/* Skip token */
-		while (*h && !vct_issepctl(*h))
+		/* Skip until end of header or comma */
+		while (*h && *h != ',')
 			h++;
 	}
 	return (0);
 }
 
 /*--------------------------------------------------------------------
+ * Find a given headerfields Q value.
+ */
+
+double
+http_GetHdrQ(const struct http *hp, const char *hdr, const char *field)
+{
+	char *h;
+	int i;
+	double a, b;
+
+	h = NULL;
+	i = http_GetHdrData(hp, hdr, field, &h);
+	if (!i)
+		return (0.);
+
+	if (h == NULL) 
+		return (1.);
+	/* Skip whitespace, looking for '=' */
+	while (*h && vct_issp(*h))
+		h++;
+	if (*h++ != ';') 
+		return (1.);
+	while (*h && vct_issp(*h))
+		h++;
+	if (*h++ != 'q') 
+		return (1.);
+	while (*h && vct_issp(*h))
+		h++;
+	if (*h++ != '=') 
+		return (1.);
+	while (*h && vct_issp(*h))
+		h++;
+	a = 0.;
+	while (vct_isdigit(*h)) {
+		a *= 10.;
+		a += *h - '0';
+		h++;
+	}
+	if (*h++ != '.')
+		return (a);
+	b = .1;
+	while (vct_isdigit(*h)) {
+		a += b * (*h - '0');
+		b *= .1;
+		h++;
+	}
+	return (a);
+}
+
+/*--------------------------------------------------------------------
+ * Find a given headerfields value.
+ */
+
+int
+http_GetHdrField(const struct http *hp, const char *hdr,
+    const char *field, char **ptr)
+{
+	char *h;
+	int i;
+
+	if (ptr != NULL)
+		*ptr = NULL;
+
+	h = NULL;
+	i = http_GetHdrData(hp, hdr, field, &h);
+	if (!i)
+		return (i);
+
+	if (ptr != NULL && h != NULL) {
+		/* Skip whitespace, looking for '=' */
+		while (*h && vct_issp(*h))
+			h++;
+		if (*h == '=') {
+			h++;
+			while (*h && vct_issp(*h))
+				h++;
+			*ptr = h;
+		}
+	}
+	return (i);
+}
+
+/*--------------------------------------------------------------------
  * XXX: redo with http_GetHdrField() ?
  */
 

Modified: trunk/varnish-cache/bin/varnishd/cache_vrt_var.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_vrt_var.c	2010-12-28 14:43:15 UTC (rev 5665)
+++ trunk/varnish-cache/bin/varnishd/cache_vrt_var.c	2010-12-30 13:14:21 UTC (rev 5666)
@@ -425,6 +425,17 @@
 
 /*--------------------------------------------------------------------*/
 
+unsigned __match_proto__()
+VRT_r_req_can_gzip(struct sess *sp)
+{
+
+	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+	return (RFC2616_Req_Gzip(sp));
+}
+
+
+/*--------------------------------------------------------------------*/
+
 int
 VRT_r_req_restarts(const struct sess *sp)
 {

Modified: trunk/varnish-cache/bin/varnishd/rfc2616.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/rfc2616.c	2010-12-28 14:43:15 UTC (rev 5665)
+++ trunk/varnish-cache/bin/varnishd/rfc2616.c	2010-12-30 13:14:21 UTC (rev 5666)
@@ -259,3 +259,32 @@
 	sp->wrk->stats.fetch_eof++;
 	return (BS_EOF);
 }
+
+/*--------------------------------------------------------------------
+ * Find out if the request can receive a gzip'ed response
+ */
+
+unsigned
+RFC2616_Req_Gzip(const struct sess *sp)
+{
+
+
+	/*
+	 * "x-gzip" is for http/1.0 backwards compat, final note in 14.3
+	 * p104 says to not do q values for x-gzip, so we just test
+	 * for its existence.
+	 */
+	if (http_GetHdrData(sp->http, H_Accept_Encoding, "x-gzip", NULL))
+		return (1);
+
+	/*
+ 	 * "gzip" is the real thing, but the 'q' value must be nonzero.
+	 * We do not care a hoot if the client prefers some other
+	 * compression more than gzip: Varnish only does gzip.
+	 */
+	if (http_GetHdrQ(sp->http, H_Accept_Encoding, "gzip") > 0.)
+		return (1);
+
+	/* Bad client, no gzip. */
+	return (0);
+}

Added: trunk/varnish-cache/bin/varnishtest/tests/g00000.vtc
===================================================================
--- trunk/varnish-cache/bin/varnishtest/tests/g00000.vtc	                        (rev 0)
+++ trunk/varnish-cache/bin/varnishtest/tests/g00000.vtc	2010-12-30 13:14:21 UTC (rev 5666)
@@ -0,0 +1,49 @@
+# $Id$
+
+test "test req.can_gzip VCL variable"
+
+server s1 {
+	rxreq
+	txresp -bodylen 4
+} -start
+
+
+varnish v1 -vcl+backend { 
+	sub vcl_deliver {
+		set resp.http.gzip = req.can_gzip;
+	}
+} -start
+
+client c1 {
+	txreq -hdr "Accept-Encoding: gzip, deflate"
+	rxresp
+	expect resp.http.gzip == "true"
+
+	txreq -hdr "Accept-Encoding: gzip;q=0.7, *;q=0"
+	rxresp
+	expect resp.http.gzip == "true"
+
+	txreq -hdr "Accept-Encoding: deflate;q=0.7, *;q=0"
+	rxresp
+	expect resp.http.gzip == "false"
+
+	txreq -hdr "Accept-Encoding: x-gzip;q=0.4, gzip"
+	rxresp
+	expect resp.http.gzip == "true"
+
+	txreq -hdr "Accept-Encoding: gzip;q=0, x-gzip"
+	rxresp
+	expect resp.http.gzip == "true"
+
+	txreq -hdr "Accept-Encoding: gzip;q=0"
+	rxresp
+	expect resp.http.gzip == "false"
+
+	txreq -hdr "Accept-Encoding: gzip;q=-1"
+	rxresp
+	expect resp.http.gzip == "false"
+
+	txreq -hdr "Accept-Encoding: gzip;q=0.0000001"
+	rxresp
+	expect resp.http.gzip == "true"
+} -run

Modified: trunk/varnish-cache/lib/libvcl/generate.py
===================================================================
--- trunk/varnish-cache/lib/libvcl/generate.py	2010-12-28 14:43:15 UTC (rev 5665)
+++ trunk/varnish-cache/lib/libvcl/generate.py	2010-12-30 13:14:21 UTC (rev 5666)
@@ -190,6 +190,12 @@
 		( 'recv', 'fetch', 'deliver', 'error',),
 		'struct sess *'
 	),
+	('req.can_gzip',
+		'BOOL',
+		( 'all',),
+		( ),
+		'struct sess *'
+	),
 	('req.backend.healthy',
 		'BOOL',
 		( 'all',),




More information about the varnish-commit mailing list