| 299 | |
| 300 | |
| 301 | bool Request::acceptsEncoding(const string& encoding) const |
| 302 | { |
| 303 | // From RFC 2616: |
| 304 | // |
| 305 | // 1. If the content-coding is one of the content-codings listed in |
| 306 | // the Accept-Encoding field, then it is acceptable, unless it is |
| 307 | // accompanied by a qvalue of 0. (As defined in section 3.9, a |
| 308 | // qvalue of 0 means "not acceptable.") |
| 309 | // |
| 310 | // 2. The special "*" symbol in an Accept-Encoding field matches any |
| 311 | // available content-coding not explicitly listed in the header |
| 312 | // field. |
| 313 | // |
| 314 | // 3. If multiple content-codings are acceptable, then the acceptable |
| 315 | // content-coding with the highest non-zero qvalue is preferred. |
| 316 | // |
| 317 | // 4. The "identity" content-coding is always acceptable, unless |
| 318 | // specifically refused because the Accept-Encoding field includes |
| 319 | // "identity;q=0", or because the field includes "*;q=0" and does |
| 320 | // not explicitly include the "identity" content-coding. If the |
| 321 | // Accept-Encoding field-value is empty, then only the "identity" |
| 322 | // encoding is acceptable. |
| 323 | // |
| 324 | // If no Accept-Encoding field is present in a request, the server |
| 325 | // MAY assume that the client will accept any content coding. In |
| 326 | // this case, if "identity" is one of the available content-codings, |
| 327 | // then the server SHOULD use the "identity" content-coding... |
| 328 | Option<string> accept = headers.get("Accept-Encoding"); |
| 329 | |
| 330 | if (accept.isNone() || accept->empty()) { |
| 331 | return false; |
| 332 | } |
| 333 | |
| 334 | // Remove spaces and tabs for easier parsing. |
| 335 | accept = strings::remove(accept.get(), " "); |
| 336 | accept = strings::remove(accept.get(), "\t"); |
| 337 | accept = strings::remove(accept.get(), "\n"); |
| 338 | |
| 339 | // First we'll look for the encoding specified explicitly, then '*'. |
| 340 | vector<string> candidates; |
| 341 | candidates.push_back(encoding); // Rule 1. |
| 342 | candidates.push_back("*"); // Rule 2. |
| 343 | |
| 344 | foreach (const string& candidate, candidates) { |
| 345 | // Is the candidate one of the accepted encodings? |
| 346 | foreach (const string& encoding_, strings::tokenize(accept.get(), ",")) { |
| 347 | vector<string> tokens = strings::tokenize(encoding_, ";"); |
| 348 | |
| 349 | if (tokens.empty()) { |
| 350 | continue; |
| 351 | } |
| 352 | |
| 353 | if (strings::lower(tokens[0]) == strings::lower(candidate)) { |
| 354 | // Is there a 0 q value? Ex: 'gzip;q=0.0'. |
| 355 | const map<string, vector<string>> values = |
| 356 | strings::pairs(encoding_, ";", "="); |
| 357 | |
| 358 | // Look for { "q": ["0"] }. |