Accept-Encoding refactoring: "gzip; q=0" support

This commit is contained in:
Igor Sysoev 2011-08-01 11:02:12 +00:00
parent d743a2339e
commit 721f47ed3c

View File

@ -70,6 +70,7 @@ static char *ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd,
static char *ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
#if (NGX_HTTP_GZIP)
static ngx_int_t ngx_http_gzip_accept_encoding(ngx_str_t *ae);
static char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
#endif
@ -2013,7 +2014,6 @@ ngx_http_auth_basic_user(ngx_http_request_t *r)
ngx_int_t
ngx_http_gzip_ok(ngx_http_request_t *r)
{
u_char *g;
time_t date, expires;
ngx_uint_t p;
ngx_array_t *cc;
@ -2031,24 +2031,24 @@ ngx_http_gzip_ok(ngx_http_request_t *r)
return NGX_DECLINED;
}
if (ngx_strncmp(ae->value.data, "gzip,", 5) == 0) {
/*
* test for the most common case "gzip,...":
* MSIE: "gzip, deflate"
* Firefox: "gzip,deflate"
* Chrome: "gzip,deflate,sdch"
* Safari: "gzip, deflate"
* Opera: "gzip, deflate"
*/
goto found;
}
g = ngx_strcasestrn(ae->value.data, "gzip", 4 - 1);
if (g == NULL) {
if (ae->value.len < 5) {
return NGX_DECLINED;
}
found:
/*
* test first for the most common case "gzip,...":
* MSIE: "gzip, deflate"
* Firefox: "gzip,deflate"
* Chrome: "gzip,deflate,sdch"
* Safari: "gzip, deflate"
* Opera: "gzip, deflate"
*/
if (ngx_memcmp(ae->value.data, "gzip,", 5) != 0
&& ngx_http_gzip_accept_encoding(&ae->value) != NGX_OK)
{
return NGX_DECLINED;
}
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
@ -2171,6 +2171,127 @@ ok:
return NGX_OK;
}
/*
* gzip is enabled for the following quantities:
* "gzip; q=0.001" ... "gzip; q=0.999", "gzip; q=1"
* gzip is disabled for the following quantities:
* "gzip; q=0" ... "gzip; q=0.000", and for any invalid cases
*/
static ngx_int_t
ngx_http_gzip_accept_encoding(ngx_str_t *ae)
{
u_char c, *p, *start, *last;
ngx_uint_t n, q;
start = ae->data;
last = start + ae->len;
for ( ;; ) {
p = ngx_strcasestrn(start, "gzip", 4 - 1);
if (p == NULL) {
return NGX_DECLINED;
}
if (p > start && (*(p - 1) == ',' || *(p - 1) == ' ')) {
break;
}
start = p + 4;
}
p += 4;
while (p < last) {
switch(*p++) {
case ',':
return NGX_OK;
case ';':
goto quantity;
case ' ':
continue;
default:
return NGX_DECLINED;
}
}
return NGX_OK;
quantity:
while (p < last) {
switch(*p++) {
case 'q':
case 'Q':
goto equal;
case ' ':
continue;
default:
return NGX_DECLINED;
}
}
return NGX_OK;
equal:
if (p + 2 > last || *p++ != '=') {
return NGX_DECLINED;
}
c = *p++;
if (c == '1') {
if (p == last || *p == ',' || *p == ' ') {
return NGX_OK;
}
return NGX_DECLINED;
}
if (c != '0') {
return NGX_DECLINED;
}
if (p == last) {
return NGX_DECLINED;
}
if (*p++ != '.') {
return NGX_DECLINED;
}
n = 0;
q = 0;
while (p < last) {
c = *p++;
if (c == ',') {
break;
}
if (c >= '1' && c <= '9') {
n++;
q++;
continue;
}
if (c == '0') {
n++;
continue;
}
return NGX_DECLINED;
}
if (n < 4 && q != 0) {
return NGX_OK;
}
return NGX_DECLINED;
}
#endif