comparison src/http/ngx_http_core_module.c @ 3980:19de03b4217f

Accept-Encoding refactoring: "gzip; q=0" support
author Igor Sysoev <igor@sysoev.ru>
date Mon, 01 Aug 2011 11:02:12 +0000
parents 1d9353fbc077
children aab3889c41e9
comparison
equal deleted inserted replaced
3979:1d9353fbc077 3980:19de03b4217f
68 static char *ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd, 68 static char *ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd,
69 void *conf); 69 void *conf);
70 static char *ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, 70 static char *ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
71 void *conf); 71 void *conf);
72 #if (NGX_HTTP_GZIP) 72 #if (NGX_HTTP_GZIP)
73 static ngx_int_t ngx_http_gzip_accept_encoding(ngx_str_t *ae);
73 static char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd, 74 static char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd,
74 void *conf); 75 void *conf);
75 #endif 76 #endif
76 77
77 static char *ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data); 78 static char *ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data);
2011 #if (NGX_HTTP_GZIP) 2012 #if (NGX_HTTP_GZIP)
2012 2013
2013 ngx_int_t 2014 ngx_int_t
2014 ngx_http_gzip_ok(ngx_http_request_t *r) 2015 ngx_http_gzip_ok(ngx_http_request_t *r)
2015 { 2016 {
2016 u_char *g;
2017 time_t date, expires; 2017 time_t date, expires;
2018 ngx_uint_t p; 2018 ngx_uint_t p;
2019 ngx_array_t *cc; 2019 ngx_array_t *cc;
2020 ngx_table_elt_t *e, *d, *ae; 2020 ngx_table_elt_t *e, *d, *ae;
2021 ngx_http_core_loc_conf_t *clcf; 2021 ngx_http_core_loc_conf_t *clcf;
2029 ae = r->headers_in.accept_encoding; 2029 ae = r->headers_in.accept_encoding;
2030 if (ae == NULL) { 2030 if (ae == NULL) {
2031 return NGX_DECLINED; 2031 return NGX_DECLINED;
2032 } 2032 }
2033 2033
2034 if (ngx_strncmp(ae->value.data, "gzip,", 5) == 0) { 2034 if (ae->value.len < 5) {
2035 /*
2036 * test for the most common case "gzip,...":
2037 * MSIE: "gzip, deflate"
2038 * Firefox: "gzip,deflate"
2039 * Chrome: "gzip,deflate,sdch"
2040 * Safari: "gzip, deflate"
2041 * Opera: "gzip, deflate"
2042 */
2043 goto found;
2044 }
2045
2046 g = ngx_strcasestrn(ae->value.data, "gzip", 4 - 1);
2047 if (g == NULL) {
2048 return NGX_DECLINED; 2035 return NGX_DECLINED;
2049 } 2036 }
2050 2037
2051 found: 2038 /*
2039 * test first for the most common case "gzip,...":
2040 * MSIE: "gzip, deflate"
2041 * Firefox: "gzip,deflate"
2042 * Chrome: "gzip,deflate,sdch"
2043 * Safari: "gzip, deflate"
2044 * Opera: "gzip, deflate"
2045 */
2046
2047 if (ngx_memcmp(ae->value.data, "gzip,", 5) != 0
2048 && ngx_http_gzip_accept_encoding(&ae->value) != NGX_OK)
2049 {
2050 return NGX_DECLINED;
2051 }
2052 2052
2053 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 2053 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2054 2054
2055 if (r->headers_in.msie6 && clcf->gzip_disable_msie6) { 2055 if (r->headers_in.msie6 && clcf->gzip_disable_msie6) {
2056 return NGX_DECLINED; 2056 return NGX_DECLINED;
2167 #endif 2167 #endif
2168 2168
2169 r->gzip_ok = 1; 2169 r->gzip_ok = 1;
2170 2170
2171 return NGX_OK; 2171 return NGX_OK;
2172 }
2173
2174
2175 /*
2176 * gzip is enabled for the following quantities:
2177 * "gzip; q=0.001" ... "gzip; q=0.999", "gzip; q=1"
2178 * gzip is disabled for the following quantities:
2179 * "gzip; q=0" ... "gzip; q=0.000", and for any invalid cases
2180 */
2181
2182 static ngx_int_t
2183 ngx_http_gzip_accept_encoding(ngx_str_t *ae)
2184 {
2185 u_char c, *p, *start, *last;
2186 ngx_uint_t n, q;
2187
2188 start = ae->data;
2189 last = start + ae->len;
2190
2191 for ( ;; ) {
2192 p = ngx_strcasestrn(start, "gzip", 4 - 1);
2193 if (p == NULL) {
2194 return NGX_DECLINED;
2195 }
2196
2197 if (p > start && (*(p - 1) == ',' || *(p - 1) == ' ')) {
2198 break;
2199 }
2200
2201 start = p + 4;
2202 }
2203
2204 p += 4;
2205
2206 while (p < last) {
2207 switch(*p++) {
2208 case ',':
2209 return NGX_OK;
2210 case ';':
2211 goto quantity;
2212 case ' ':
2213 continue;
2214 default:
2215 return NGX_DECLINED;
2216 }
2217 }
2218
2219 return NGX_OK;
2220
2221 quantity:
2222
2223 while (p < last) {
2224 switch(*p++) {
2225 case 'q':
2226 case 'Q':
2227 goto equal;
2228 case ' ':
2229 continue;
2230 default:
2231 return NGX_DECLINED;
2232 }
2233 }
2234
2235 return NGX_OK;
2236
2237 equal:
2238
2239 if (p + 2 > last || *p++ != '=') {
2240 return NGX_DECLINED;
2241 }
2242
2243 c = *p++;
2244
2245 if (c == '1') {
2246 if (p == last || *p == ',' || *p == ' ') {
2247 return NGX_OK;
2248 }
2249 return NGX_DECLINED;
2250 }
2251
2252 if (c != '0') {
2253 return NGX_DECLINED;
2254 }
2255
2256 if (p == last) {
2257 return NGX_DECLINED;
2258 }
2259
2260 if (*p++ != '.') {
2261 return NGX_DECLINED;
2262 }
2263
2264 n = 0;
2265 q = 0;
2266
2267 while (p < last) {
2268 c = *p++;
2269
2270 if (c == ',') {
2271 break;
2272 }
2273
2274 if (c >= '1' && c <= '9') {
2275 n++;
2276 q++;
2277 continue;
2278 }
2279
2280 if (c == '0') {
2281 n++;
2282 continue;
2283 }
2284
2285 return NGX_DECLINED;
2286 }
2287
2288 if (n < 4 && q != 0) {
2289 return NGX_OK;
2290 }
2291
2292 return NGX_DECLINED;
2172 } 2293 }
2173 2294
2174 #endif 2295 #endif
2175 2296
2176 2297