comparison src/http/ngx_http_core_module.c @ 4040:0094c8636d5f stable-1.0

Merge of r3979, r3980, r3981, r3983, r3987, r3994, r3995: Accept-Encoding refactoring: *) "gzip; q=0" support *) and removal of ancient MSIE 4.x test for gzip
author Igor Sysoev <igor@sysoev.ru>
date Mon, 29 Aug 2011 10:39:23 +0000
parents 1df827cf70c0
children d9b486dbf7e5
comparison
equal deleted inserted replaced
4039:ee270f311dea 4040:0094c8636d5f
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);
74 static ngx_uint_t ngx_http_gzip_quantity(u_char *p, u_char *last);
73 static char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd, 75 static char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd,
74 void *conf); 76 void *conf);
75 #endif 77 #endif
76 78
77 static char *ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data); 79 static char *ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data);
2014 ngx_http_gzip_ok(ngx_http_request_t *r) 2016 ngx_http_gzip_ok(ngx_http_request_t *r)
2015 { 2017 {
2016 time_t date, expires; 2018 time_t date, expires;
2017 ngx_uint_t p; 2019 ngx_uint_t p;
2018 ngx_array_t *cc; 2020 ngx_array_t *cc;
2019 ngx_table_elt_t *e, *d; 2021 ngx_table_elt_t *e, *d, *ae;
2020 ngx_http_core_loc_conf_t *clcf; 2022 ngx_http_core_loc_conf_t *clcf;
2021 2023
2022 r->gzip_tested = 1; 2024 r->gzip_tested = 1;
2023 2025
2024 if (r != r->main 2026 if (r != r->main) {
2025 || r->headers_in.accept_encoding == NULL 2027 return NGX_DECLINED;
2026 || ngx_strcasestrn(r->headers_in.accept_encoding->value.data, 2028 }
2027 "gzip", 4 - 1) 2029
2028 == NULL 2030 ae = r->headers_in.accept_encoding;
2029 2031 if (ae == NULL) {
2030 /* 2032 return NGX_DECLINED;
2031 * if the URL (without the "http://" prefix) is longer than 253 bytes, 2033 }
2032 * then MSIE 4.x can not handle the compressed stream - it waits 2034
2033 * too long, hangs up or crashes 2035 if (ae->value.len < sizeof("gzip") - 1) {
2034 */ 2036 return NGX_DECLINED;
2035 2037 }
2036 || (r->headers_in.msie4 && r->unparsed_uri.len > 200)) 2038
2039 /*
2040 * test first for the most common case "gzip,...":
2041 * MSIE: "gzip, deflate"
2042 * Firefox: "gzip,deflate"
2043 * Chrome: "gzip,deflate,sdch"
2044 * Safari: "gzip, deflate"
2045 * Opera: "gzip, deflate"
2046 */
2047
2048 if (ngx_memcmp(ae->value.data, "gzip,", 5) != 0
2049 && ngx_http_gzip_accept_encoding(&ae->value) != NGX_OK)
2037 { 2050 {
2038 return NGX_DECLINED; 2051 return NGX_DECLINED;
2039 } 2052 }
2040 2053
2041 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 2054 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2155 #endif 2168 #endif
2156 2169
2157 r->gzip_ok = 1; 2170 r->gzip_ok = 1;
2158 2171
2159 return NGX_OK; 2172 return NGX_OK;
2173 }
2174
2175
2176 /*
2177 * gzip is enabled for the following quantities:
2178 * "gzip; q=0.001" ... "gzip; q=1.000"
2179 * gzip is disabled for the following quantities:
2180 * "gzip; q=0" ... "gzip; q=0.000", and for any invalid cases
2181 */
2182
2183 static ngx_int_t
2184 ngx_http_gzip_accept_encoding(ngx_str_t *ae)
2185 {
2186 u_char *p, *start, *last;
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 if (ngx_http_gzip_quantity(p, last) == 0) {
2244 return NGX_DECLINED;
2245 }
2246
2247 return NGX_OK;
2248 }
2249
2250
2251 ngx_uint_t
2252 ngx_http_gzip_quantity(u_char *p, u_char *last)
2253 {
2254 u_char c;
2255 ngx_uint_t n, q;
2256
2257 c = *p++;
2258
2259 if (c != '0' && c != '1') {
2260 return 0;
2261 }
2262
2263 q = (c - '0') * 100;
2264
2265 if (p == last) {
2266 return q;
2267 }
2268
2269 c = *p++;
2270
2271 if (c == ',' || c == ' ') {
2272 return q;
2273 }
2274
2275 if (c != '.') {
2276 return 0;
2277 }
2278
2279 n = 0;
2280
2281 while (p < last) {
2282 c = *p++;
2283
2284 if (c == ',' || c == ' ') {
2285 break;
2286 }
2287
2288 if (c >= '0' && c <= '9') {
2289 q += c - '0';
2290 n++;
2291 continue;
2292 }
2293
2294 return 0;
2295 }
2296
2297 if (q > 100 || n > 3) {
2298 return 0;
2299 }
2300
2301 return q;
2160 } 2302 }
2161 2303
2162 #endif 2304 #endif
2163 2305
2164 2306