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