OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_heade rs.h" | 5 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_heade rs.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <string> | 10 #include <string> |
11 #include <utility> | 11 #include <utility> |
12 #include <vector> | 12 #include <vector> |
13 | 13 |
14 #include "base/rand_util.h" | 14 #include "base/rand_util.h" |
15 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
16 #include "base/strings/string_split.h" | 16 #include "base/strings/string_split.h" |
17 #include "base/strings/string_util.h" | 17 #include "base/strings/string_util.h" |
18 #include "base/time/time.h" | 18 #include "base/time/time.h" |
19 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_event _creator.h" | 19 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_event _creator.h" |
20 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_param s.h" | 20 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_param s.h" |
21 #include "net/http/http_response_headers.h" | 21 #include "net/http/http_response_headers.h" |
22 #include "net/http/http_status_code.h" | 22 #include "net/http/http_status_code.h" |
23 #include "net/url_request/url_request.h" | |
23 | 24 |
24 using base::StringPiece; | 25 using base::StringPiece; |
25 using base::TimeDelta; | 26 using base::TimeDelta; |
26 | 27 |
27 namespace { | 28 namespace { |
28 | 29 |
29 const char kChromeProxyHeader[] = "chrome-proxy"; | 30 const char kChromeProxyHeader[] = "chrome-proxy"; |
30 const char kChromeProxyECTHeader[] = "chrome-proxy-ect"; | 31 const char kChromeProxyECTHeader[] = "chrome-proxy-ect"; |
31 const char kChromeProxyAcceptTransformHeader[] = | 32 const char kChromeProxyAcceptTransformHeader[] = |
32 "chrome-proxy-accept-transform"; | 33 "chrome-proxy-accept-transform"; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
99 const std::string& transform_type) { | 100 const std::string& transform_type) { |
100 std::string header_value; | 101 std::string header_value; |
101 if (!headers.GetNormalizedHeader( | 102 if (!headers.GetNormalizedHeader( |
102 data_reduction_proxy::chrome_proxy_content_transform_header(), | 103 data_reduction_proxy::chrome_proxy_content_transform_header(), |
103 &header_value)) { | 104 &header_value)) { |
104 return false; | 105 return false; |
105 } | 106 } |
106 return IsPreviewTypeInHeaderValue(header_value, transform_type); | 107 return IsPreviewTypeInHeaderValue(header_value, transform_type); |
107 } | 108 } |
108 | 109 |
110 // Returns true if there is a cycle in |url_chain|. | |
111 bool HasURLRedirectCycle(const std::vector<GURL>& url_chain) { | |
112 if (url_chain.size() <= 1) | |
113 return false; | |
114 | |
115 // If the last entry occurs more than once, then very likely there is a | |
116 // redirect cycle. | |
117 GURL last_entry = url_chain.back(); | |
118 size_t last_entry_number_occurences = 0; | |
119 | |
120 for (const auto& url : url_chain) { | |
121 if (url == last_entry) { | |
122 last_entry_number_occurences++; | |
123 if (last_entry_number_occurences >= 2) | |
RyanSturm
2017/03/28 18:03:19
This looks confusing with the >=2 condition. Since
tbansal1
2017/03/28 19:59:48
Done.
| |
124 return true; | |
125 } | |
126 } | |
127 return false; | |
128 } | |
129 | |
109 } // namespace | 130 } // namespace |
110 | 131 |
111 namespace data_reduction_proxy { | 132 namespace data_reduction_proxy { |
112 | 133 |
113 const char* chrome_proxy_header() { | 134 const char* chrome_proxy_header() { |
114 return kChromeProxyHeader; | 135 return kChromeProxyHeader; |
115 } | 136 } |
116 | 137 |
117 const char* chrome_proxy_ect_header() { | 138 const char* chrome_proxy_ect_header() { |
118 return kChromeProxyECTHeader; | 139 return kChromeProxyECTHeader; |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
276 // the data reduction proxy's Via header. | 297 // the data reduction proxy's Via header. |
277 *has_intermediary = !(headers->EnumerateHeader(&iter, "via", &value)); | 298 *has_intermediary = !(headers->EnumerateHeader(&iter, "via", &value)); |
278 return true; | 299 return true; |
279 } | 300 } |
280 } | 301 } |
281 | 302 |
282 return false; | 303 return false; |
283 } | 304 } |
284 | 305 |
285 DataReductionProxyBypassType GetDataReductionProxyBypassType( | 306 DataReductionProxyBypassType GetDataReductionProxyBypassType( |
286 const net::HttpResponseHeaders* headers, | 307 const std::vector<GURL>& url_chain, |
308 const net::HttpResponseHeaders& headers, | |
287 DataReductionProxyInfo* data_reduction_proxy_info) { | 309 DataReductionProxyInfo* data_reduction_proxy_info) { |
288 DCHECK(data_reduction_proxy_info); | 310 DCHECK(data_reduction_proxy_info); |
289 if (ParseHeadersForBypassInfo(headers, data_reduction_proxy_info)) { | 311 |
312 bool has_via_header = HasDataReductionProxyViaHeader(&headers, nullptr); | |
RyanSturm
2017/03/28 18:03:19
Any chance you want to change HasDataReductionProx
tbansal1
2017/03/28 19:59:48
I was planning to do it in a separate CL, but I ha
| |
313 | |
314 if (has_via_header && HasURLRedirectCycle(url_chain)) { | |
315 data_reduction_proxy_info->bypass_all = true; | |
316 data_reduction_proxy_info->mark_proxies_as_bad = false; | |
317 data_reduction_proxy_info->bypass_duration = base::TimeDelta(); | |
318 data_reduction_proxy_info->bypass_action = BYPASS_ACTION_TYPE_BLOCK_ONCE; | |
319 return BYPASS_EVENT_TYPE_URL_REDIRECT_CYCLE; | |
320 } | |
321 | |
322 if (ParseHeadersForBypassInfo(&headers, data_reduction_proxy_info)) { | |
290 // A chrome-proxy response header is only present in a 502. For proper | 323 // A chrome-proxy response header is only present in a 502. For proper |
291 // reporting, this check must come before the 5xx checks below. | 324 // reporting, this check must come before the 5xx checks below. |
292 if (!data_reduction_proxy_info->mark_proxies_as_bad) | 325 if (!data_reduction_proxy_info->mark_proxies_as_bad) |
293 return BYPASS_EVENT_TYPE_CURRENT; | 326 return BYPASS_EVENT_TYPE_CURRENT; |
294 | 327 |
295 const TimeDelta& duration = data_reduction_proxy_info->bypass_duration; | 328 const TimeDelta& duration = data_reduction_proxy_info->bypass_duration; |
296 if (duration <= TimeDelta::FromSeconds(kShortBypassMaxSeconds)) | 329 if (duration <= TimeDelta::FromSeconds(kShortBypassMaxSeconds)) |
297 return BYPASS_EVENT_TYPE_SHORT; | 330 return BYPASS_EVENT_TYPE_SHORT; |
298 if (duration <= TimeDelta::FromSeconds(kMediumBypassMaxSeconds)) | 331 if (duration <= TimeDelta::FromSeconds(kMediumBypassMaxSeconds)) |
299 return BYPASS_EVENT_TYPE_MEDIUM; | 332 return BYPASS_EVENT_TYPE_MEDIUM; |
300 return BYPASS_EVENT_TYPE_LONG; | 333 return BYPASS_EVENT_TYPE_LONG; |
301 } | 334 } |
302 | 335 |
303 // If a bypass is triggered by any of the following cases, then the data | 336 // If a bypass is triggered by any of the following cases, then the data |
304 // reduction proxy should be bypassed for a random duration between 1 and 5 | 337 // reduction proxy should be bypassed for a random duration between 1 and 5 |
305 // minutes. | 338 // minutes. |
306 data_reduction_proxy_info->mark_proxies_as_bad = true; | 339 data_reduction_proxy_info->mark_proxies_as_bad = true; |
307 data_reduction_proxy_info->bypass_duration = GetDefaultBypassDuration(); | 340 data_reduction_proxy_info->bypass_duration = GetDefaultBypassDuration(); |
308 | 341 |
309 // Fall back if a 500, 502 or 503 is returned. | 342 // Fall back if a 500, 502 or 503 is returned. |
310 if (headers->response_code() == net::HTTP_INTERNAL_SERVER_ERROR) | 343 if (headers.response_code() == net::HTTP_INTERNAL_SERVER_ERROR) |
311 return BYPASS_EVENT_TYPE_STATUS_500_HTTP_INTERNAL_SERVER_ERROR; | 344 return BYPASS_EVENT_TYPE_STATUS_500_HTTP_INTERNAL_SERVER_ERROR; |
312 if (headers->response_code() == net::HTTP_BAD_GATEWAY) | 345 if (headers.response_code() == net::HTTP_BAD_GATEWAY) |
313 return BYPASS_EVENT_TYPE_STATUS_502_HTTP_BAD_GATEWAY; | 346 return BYPASS_EVENT_TYPE_STATUS_502_HTTP_BAD_GATEWAY; |
314 if (headers->response_code() == net::HTTP_SERVICE_UNAVAILABLE) | 347 if (headers.response_code() == net::HTTP_SERVICE_UNAVAILABLE) |
315 return BYPASS_EVENT_TYPE_STATUS_503_HTTP_SERVICE_UNAVAILABLE; | 348 return BYPASS_EVENT_TYPE_STATUS_503_HTTP_SERVICE_UNAVAILABLE; |
316 // TODO(kundaji): Bypass if Proxy-Authenticate header value cannot be | 349 // TODO(kundaji): Bypass if Proxy-Authenticate header value cannot be |
317 // interpreted by data reduction proxy. | 350 // interpreted by data reduction proxy. |
318 if (headers->response_code() == net::HTTP_PROXY_AUTHENTICATION_REQUIRED && | 351 if (headers.response_code() == net::HTTP_PROXY_AUTHENTICATION_REQUIRED && |
319 !headers->HasHeader("Proxy-Authenticate")) { | 352 !headers.HasHeader("Proxy-Authenticate")) { |
320 return BYPASS_EVENT_TYPE_MALFORMED_407; | 353 return BYPASS_EVENT_TYPE_MALFORMED_407; |
321 } | 354 } |
322 if (!HasDataReductionProxyViaHeader(headers, NULL) && | 355 if (!has_via_header && (headers.response_code() != net::HTTP_NOT_MODIFIED)) { |
323 (headers->response_code() != net::HTTP_NOT_MODIFIED)) { | |
324 // A Via header might not be present in a 304. Since the goal of a 304 | 356 // A Via header might not be present in a 304. Since the goal of a 304 |
325 // response is to minimize information transfer, a sender in general | 357 // response is to minimize information transfer, a sender in general |
326 // should not generate representation metadata other than Cache-Control, | 358 // should not generate representation metadata other than Cache-Control, |
327 // Content-Location, Date, ETag, Expires, and Vary. | 359 // Content-Location, Date, ETag, Expires, and Vary. |
328 | 360 |
329 // The proxy Via header might also not be present in a 4xx response. | 361 // The proxy Via header might also not be present in a 4xx response. |
330 // Separate this case from other responses that are missing the header. | 362 // Separate this case from other responses that are missing the header. |
331 if (headers->response_code() >= net::HTTP_BAD_REQUEST && | 363 if (headers.response_code() >= net::HTTP_BAD_REQUEST && |
332 headers->response_code() < net::HTTP_INTERNAL_SERVER_ERROR) { | 364 headers.response_code() < net::HTTP_INTERNAL_SERVER_ERROR) { |
333 // At this point, any 4xx response that is missing the via header | 365 // At this point, any 4xx response that is missing the via header |
334 // indicates an issue that is scoped to only the current request, so only | 366 // indicates an issue that is scoped to only the current request, so only |
335 // bypass the data reduction proxy for the current request. | 367 // bypass the data reduction proxy for the current request. |
336 data_reduction_proxy_info->bypass_all = true; | 368 data_reduction_proxy_info->bypass_all = true; |
337 data_reduction_proxy_info->mark_proxies_as_bad = false; | 369 data_reduction_proxy_info->mark_proxies_as_bad = false; |
338 data_reduction_proxy_info->bypass_duration = TimeDelta(); | 370 data_reduction_proxy_info->bypass_duration = TimeDelta(); |
339 return BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_4XX; | 371 return BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_4XX; |
340 } | 372 } |
341 | 373 |
342 // Missing the via header should not trigger bypass if the client is | 374 // Missing the via header should not trigger bypass if the client is |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
392 std::string value; | 424 std::string value; |
393 size_t iter = 0; | 425 size_t iter = 0; |
394 while (headers->EnumerateHeader(&iter, kChromeProxyHeader, &value)) { | 426 while (headers->EnumerateHeader(&iter, kChromeProxyHeader, &value)) { |
395 if (StartsWithActionPrefix(value, kChromeProxyActionFingerprintChromeProxy)) | 427 if (StartsWithActionPrefix(value, kChromeProxyActionFingerprintChromeProxy)) |
396 continue; | 428 continue; |
397 values->push_back(std::move(value)); | 429 values->push_back(std::move(value)); |
398 } | 430 } |
399 } | 431 } |
400 | 432 |
401 } // namespace data_reduction_proxy | 433 } // namespace data_reduction_proxy |
OLD | NEW |