Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc

Issue 2777823002: Bypass DRP if a redirect cycle is detected (Closed)
Patch Set: ps Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698