Commit 6253dc26 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Add the "req.can_gzip" VCL variable, which tells if we can send gzip

to the client or not.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@5666 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent d241fc5f
......@@ -611,8 +611,11 @@ void http_SetH(const struct http *to, unsigned n, const char *fm);
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 @@ unsigned WS_Free(const struct ws *ws);
/* 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);
......
......@@ -290,12 +290,12 @@ http_GetHdr(const struct http *hp, const char *hdr, char **ptr)
/*--------------------------------------------------------------------
* 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,36 +309,112 @@ http_GetHdrField(const struct http *hp, const char *hdr,
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++;
if (*h == '=') {
h += fl;
while (vct_islws(*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() ?
*/
......
......@@ -423,6 +423,17 @@ VRT_r_req_esi(struct sess *sp)
return (!sp->disable_esi);
}
/*--------------------------------------------------------------------*/
unsigned __match_proto__()
VRT_r_req_can_gzip(struct sess *sp)
{
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
return (RFC2616_Req_Gzip(sp));
}
/*--------------------------------------------------------------------*/
int
......
......@@ -259,3 +259,32 @@ RFC2616_Body(const struct sess *sp)
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);
}
# $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
......@@ -190,6 +190,12 @@ sp_variables = (
( 'recv', 'fetch', 'deliver', 'error',),
'struct sess *'
),
('req.can_gzip',
'BOOL',
( 'all',),
( ),
'struct sess *'
),
('req.backend.healthy',
'BOOL',
( 'all',),
......
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