Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "net/http/http_network_transaction.h" | 5 #include "net/http/http_network_transaction.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 68 #endif | 68 #endif |
| 69 | 69 |
| 70 | 70 |
| 71 using base::Time; | 71 using base::Time; |
| 72 using base::TimeDelta; | 72 using base::TimeDelta; |
| 73 | 73 |
| 74 namespace net { | 74 namespace net { |
| 75 | 75 |
| 76 namespace { | 76 namespace { |
| 77 | 77 |
| 78 const int kNumRetries = 3; | |
| 79 | |
| 78 void ProcessAlternateProtocol( | 80 void ProcessAlternateProtocol( |
| 79 HttpNetworkSession* session, | 81 HttpNetworkSession* session, |
| 80 const HttpResponseHeaders& headers, | 82 const HttpResponseHeaders& headers, |
| 81 const HostPortPair& http_host_port_pair) { | 83 const HostPortPair& http_host_port_pair) { |
| 82 if (!headers.HasHeader(kAlternateProtocolHeader)) | 84 if (!headers.HasHeader(kAlternateProtocolHeader)) |
| 83 return; | 85 return; |
| 84 | 86 |
| 85 std::vector<std::string> alternate_protocol_values; | 87 std::vector<std::string> alternate_protocol_values; |
| 86 void* iter = NULL; | 88 void* iter = NULL; |
| 87 std::string alternate_protocol_str; | 89 std::string alternate_protocol_str; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 135 base::Unretained(this))), | 137 base::Unretained(this))), |
| 136 session_(session), | 138 session_(session), |
| 137 request_(NULL), | 139 request_(NULL), |
| 138 priority_(priority), | 140 priority_(priority), |
| 139 headers_valid_(false), | 141 headers_valid_(false), |
| 140 logged_response_time_(false), | 142 logged_response_time_(false), |
| 141 fallback_error_code_(ERR_SSL_INAPPROPRIATE_FALLBACK), | 143 fallback_error_code_(ERR_SSL_INAPPROPRIATE_FALLBACK), |
| 142 request_headers_(), | 144 request_headers_(), |
| 143 read_buf_len_(0), | 145 read_buf_len_(0), |
| 144 total_received_bytes_(0), | 146 total_received_bytes_(0), |
| 147 retry_attempt_(0), | |
| 148 offset_(0), | |
| 149 previous_content_length_(0), | |
| 145 next_state_(STATE_NONE), | 150 next_state_(STATE_NONE), |
| 146 establishing_tunnel_(false), | 151 establishing_tunnel_(false), |
| 147 websocket_handshake_stream_base_create_helper_(NULL) { | 152 websocket_handshake_stream_base_create_helper_(NULL) { |
| 148 session->ssl_config_service()->GetSSLConfig(&server_ssl_config_); | 153 session->ssl_config_service()->GetSSLConfig(&server_ssl_config_); |
| 149 session->GetNextProtos(&server_ssl_config_.next_protos); | 154 session->GetNextProtos(&server_ssl_config_.next_protos); |
| 150 proxy_ssl_config_ = server_ssl_config_; | 155 proxy_ssl_config_ = server_ssl_config_; |
| 151 } | 156 } |
| 152 | 157 |
| 153 HttpNetworkTransaction::~HttpNetworkTransaction() { | 158 HttpNetworkTransaction::~HttpNetworkTransaction() { |
| 154 if (stream_.get()) { | 159 if (stream_.get()) { |
| (...skipping 616 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 771 } | 776 } |
| 772 | 777 |
| 773 int HttpNetworkTransaction::DoInitStream() { | 778 int HttpNetworkTransaction::DoInitStream() { |
| 774 DCHECK(stream_.get()); | 779 DCHECK(stream_.get()); |
| 775 next_state_ = STATE_INIT_STREAM_COMPLETE; | 780 next_state_ = STATE_INIT_STREAM_COMPLETE; |
| 776 return stream_->InitializeStream(request_, priority_, net_log_, io_callback_); | 781 return stream_->InitializeStream(request_, priority_, net_log_, io_callback_); |
| 777 } | 782 } |
| 778 | 783 |
| 779 int HttpNetworkTransaction::DoInitStreamComplete(int result) { | 784 int HttpNetworkTransaction::DoInitStreamComplete(int result) { |
| 780 if (result == OK) { | 785 if (result == OK) { |
| 786 if (offset_) | |
| 787 stream_->SetRestartInfo(offset_, hash_, sizeof(hash_)); | |
| 781 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; | 788 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; |
| 782 } else { | 789 } else { |
| 783 if (result < 0) | 790 if (result < 0) |
| 784 result = HandleIOError(result); | 791 result = HandleIOError(result); |
| 785 | 792 |
| 786 // The stream initialization failed, so this stream will never be useful. | 793 // The stream initialization failed, so this stream will never be useful. |
| 787 if (stream_) | 794 if (stream_) |
| 788 total_received_bytes_ += stream_->GetTotalReceivedBytes(); | 795 total_received_bytes_ += stream_->GetTotalReceivedBytes(); |
| 789 stream_.reset(); | 796 stream_.reset(); |
| 790 } | 797 } |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 993 // bizarre for SPDY. Assuming this logic is useful at all. | 1000 // bizarre for SPDY. Assuming this logic is useful at all. |
| 994 // TODO(davidben): Bubble the error code up so we do not cache? | 1001 // TODO(davidben): Bubble the error code up so we do not cache? |
| 995 if (result == ERR_CONNECTION_CLOSED && response_.headers.get()) | 1002 if (result == ERR_CONNECTION_CLOSED && response_.headers.get()) |
| 996 result = OK; | 1003 result = OK; |
| 997 | 1004 |
| 998 if (result < 0) | 1005 if (result < 0) |
| 999 return HandleIOError(result); | 1006 return HandleIOError(result); |
| 1000 | 1007 |
| 1001 DCHECK(response_.headers.get()); | 1008 DCHECK(response_.headers.get()); |
| 1002 | 1009 |
| 1010 if ((response_.headers->response_code() == 200 || | |
| 1011 response_.headers->response_code() == 206) && offset_) { | |
| 1012 std::string etag, last_modified; | |
| 1013 response_.headers->EnumerateHeader(NULL, "last-modified", &last_modified); | |
| 1014 if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1)) | |
| 1015 response_.headers->EnumerateHeader(NULL, "etag", &etag); | |
| 1016 | |
| 1017 // Return an error if content was updated on a retry. | |
| 1018 if ((previous_content_length_ != response_.headers->GetContentLength() && | |
| 1019 response_.headers->response_code() == 200) || | |
| 1020 previous_etag_ != etag || previous_last_modified_ != last_modified) { | |
| 1021 return HandleIOError(ERR_RETRY_CONTENT_UPDATED); | |
| 1022 } | |
| 1023 } | |
| 1024 | |
| 1003 // On a 408 response from the server ("Request Timeout") on a stale socket, | 1025 // On a 408 response from the server ("Request Timeout") on a stale socket, |
| 1004 // retry the request. | 1026 // retry the request. |
| 1005 // Headers can be NULL because of http://crbug.com/384554. | 1027 // Headers can be NULL because of http://crbug.com/384554. |
| 1006 if (response_.headers.get() && response_.headers->response_code() == 408 && | 1028 if (response_.headers.get() && response_.headers->response_code() == 408 && |
| 1007 stream_->IsConnectionReused()) { | 1029 stream_->IsConnectionReused()) { |
| 1008 net_log_.AddEventWithNetErrorCode( | 1030 net_log_.AddEventWithNetErrorCode( |
| 1009 NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, | 1031 NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, |
| 1010 response_.headers->response_code()); | 1032 response_.headers->response_code()); |
| 1011 // This will close the socket - it would be weird to try and reuse it, even | 1033 // This will close the socket - it would be weird to try and reuse it, even |
| 1012 // if the server doesn't actually close it. | 1034 // if the server doesn't actually close it. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1054 | 1076 |
| 1055 int rv = HandleAuthChallenge(); | 1077 int rv = HandleAuthChallenge(); |
| 1056 if (rv != OK) | 1078 if (rv != OK) |
| 1057 return rv; | 1079 return rv; |
| 1058 | 1080 |
| 1059 if (is_https_request()) | 1081 if (is_https_request()) |
| 1060 stream_->GetSSLInfo(&response_.ssl_info); | 1082 stream_->GetSSLInfo(&response_.ssl_info); |
| 1061 | 1083 |
| 1062 headers_valid_ = true; | 1084 headers_valid_ = true; |
| 1063 | 1085 |
| 1086 if (retry_attempt_ && read_buf_.get()) | |
| 1087 next_state_ = STATE_READ_BODY; | |
| 1088 | |
| 1064 if (session_->huffman_aggregator()) { | 1089 if (session_->huffman_aggregator()) { |
| 1065 session_->huffman_aggregator()->AggregateTransactionCharacterCounts( | 1090 session_->huffman_aggregator()->AggregateTransactionCharacterCounts( |
| 1066 *request_, | 1091 *request_, |
| 1067 request_headers_, | 1092 request_headers_, |
| 1068 proxy_info_.proxy_server(), | 1093 proxy_info_.proxy_server(), |
| 1069 *response_.headers); | 1094 *response_.headers); |
| 1070 } | 1095 } |
| 1071 return OK; | 1096 return OK; |
| 1072 } | 1097 } |
| 1073 | 1098 |
| 1074 int HttpNetworkTransaction::DoReadBody() { | 1099 int HttpNetworkTransaction::DoReadBody() { |
| 1075 DCHECK(read_buf_.get()); | 1100 DCHECK(read_buf_.get()); |
| 1076 DCHECK_GT(read_buf_len_, 0); | 1101 DCHECK_GT(read_buf_len_, 0); |
| 1077 DCHECK(stream_ != NULL); | 1102 DCHECK(stream_ != NULL); |
| 1078 | 1103 |
| 1079 next_state_ = STATE_READ_BODY_COMPLETE; | 1104 next_state_ = STATE_READ_BODY_COMPLETE; |
| 1080 return stream_->ReadResponseBody( | 1105 return stream_->ReadResponseBody( |
| 1081 read_buf_.get(), read_buf_len_, io_callback_); | 1106 read_buf_.get(), read_buf_len_, io_callback_); |
| 1082 } | 1107 } |
| 1083 | 1108 |
| 1084 int HttpNetworkTransaction::DoReadBodyComplete(int result) { | 1109 int HttpNetworkTransaction::DoReadBodyComplete(int result) { |
| 1085 // We are done with the Read call. | 1110 // We are done with the Read call. |
| 1086 bool done = false; | 1111 bool done = false; |
| 1087 if (result <= 0) { | 1112 if (result <= 0) { |
| 1088 DCHECK_NE(ERR_IO_PENDING, result); | 1113 DCHECK_NE(ERR_IO_PENDING, result); |
| 1114 if (result < 0) | |
| 1115 return HandleIOError(result); | |
| 1089 done = true; | 1116 done = true; |
| 1090 } | 1117 } |
| 1091 | 1118 |
| 1092 bool keep_alive = false; | 1119 bool keep_alive = false; |
| 1093 if (stream_->IsResponseBodyComplete()) { | 1120 if (stream_->IsResponseBodyComplete()) { |
| 1094 // Note: Just because IsResponseBodyComplete is true, we're not | 1121 // Note: Just because IsResponseBodyComplete is true, we're not |
| 1095 // necessarily "done". We're only "done" when it is the last | 1122 // necessarily "done". We're only "done" when it is the last |
| 1096 // read on this HttpNetworkTransaction, which will be signified | 1123 // read on this HttpNetworkTransaction, which will be signified |
| 1097 // by a zero-length read. | 1124 // by a zero-length read. |
| 1098 // TODO(mbelshe): The keepalive property is really a property of | 1125 // TODO(mbelshe): The keepalive property is really a property of |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1220 base::TimeDelta::FromMinutes(10), 100); | 1247 base::TimeDelta::FromMinutes(10), 100); |
| 1221 | 1248 |
| 1222 if (!stream_->IsConnectionReused()) { | 1249 if (!stream_->IsConnectionReused()) { |
| 1223 UMA_HISTOGRAM_CUSTOM_TIMES( | 1250 UMA_HISTOGRAM_CUSTOM_TIMES( |
| 1224 "Net.Transaction_Latency_Total_New_Connection", | 1251 "Net.Transaction_Latency_Total_New_Connection", |
| 1225 total_duration, base::TimeDelta::FromMilliseconds(1), | 1252 total_duration, base::TimeDelta::FromMilliseconds(1), |
| 1226 base::TimeDelta::FromMinutes(10), 100); | 1253 base::TimeDelta::FromMinutes(10), 100); |
| 1227 } | 1254 } |
| 1228 } | 1255 } |
| 1229 | 1256 |
| 1257 void HttpNetworkTransaction::LogTransactionRetryMetrics(int error) const { | |
| 1258 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpRetry.Count", retry_attempt_, 1, 5, 5); | |
| 1259 if (request_->load_flags & LOAD_MAIN_FRAME) { | |
| 1260 UMA_HISTOGRAM_CUSTOM_ENUMERATION( | |
| 1261 "Net.HttpRetry.Cause.MainFrame", | |
| 1262 -error, | |
| 1263 GetAllErrorCodesForUma()); | |
| 1264 } else { | |
| 1265 UMA_HISTOGRAM_CUSTOM_ENUMERATION( | |
| 1266 "Net.HttpRetry.Cause.Subresource", | |
| 1267 -error, | |
| 1268 GetAllErrorCodesForUma()); | |
| 1269 } | |
| 1270 } | |
| 1271 | |
| 1230 int HttpNetworkTransaction::HandleCertificateRequest(int error) { | 1272 int HttpNetworkTransaction::HandleCertificateRequest(int error) { |
| 1231 // There are two paths through which the server can request a certificate | 1273 // There are two paths through which the server can request a certificate |
| 1232 // from us. The first is during the initial handshake, the second is | 1274 // from us. The first is during the initial handshake, the second is |
| 1233 // during SSL renegotiation. | 1275 // during SSL renegotiation. |
| 1234 // | 1276 // |
| 1235 // In both cases, we want to close the connection before proceeding. | 1277 // In both cases, we want to close the connection before proceeding. |
| 1236 // We do this for two reasons: | 1278 // We do this for two reasons: |
| 1237 // First, we don't want to keep the connection to the server hung for a | 1279 // First, we don't want to keep the connection to the server hung for a |
| 1238 // long time while the user selects a certificate. | 1280 // long time while the user selects a certificate. |
| 1239 // Second, even if we did keep the connection open, NSS has a bug where | 1281 // Second, even if we did keep the connection open, NSS has a bug where |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1414 // likely happen when trying to retrieve its IP address. | 1456 // likely happen when trying to retrieve its IP address. |
| 1415 // See http://crbug.com/105824 for more details. | 1457 // See http://crbug.com/105824 for more details. |
| 1416 case ERR_SOCKET_NOT_CONNECTED: | 1458 case ERR_SOCKET_NOT_CONNECTED: |
| 1417 // If a socket is closed on its initial request, HttpStreamParser returns | 1459 // If a socket is closed on its initial request, HttpStreamParser returns |
| 1418 // ERR_EMPTY_RESPONSE. This may still be close/reuse race if the socket was | 1460 // ERR_EMPTY_RESPONSE. This may still be close/reuse race if the socket was |
| 1419 // preconnected but failed to be used before the server timed it out. | 1461 // preconnected but failed to be used before the server timed it out. |
| 1420 case ERR_EMPTY_RESPONSE: | 1462 case ERR_EMPTY_RESPONSE: |
| 1421 if (ShouldResendRequest()) { | 1463 if (ShouldResendRequest()) { |
| 1422 net_log_.AddEventWithNetErrorCode( | 1464 net_log_.AddEventWithNetErrorCode( |
| 1423 NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, error); | 1465 NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, error); |
| 1466 retry_attempt_++; | |
| 1467 LogTransactionRetryMetrics(error); | |
| 1424 ResetConnectionAndRequestForResend(); | 1468 ResetConnectionAndRequestForResend(); |
| 1425 error = OK; | 1469 error = OK; |
| 1426 } | 1470 } |
| 1427 break; | 1471 break; |
| 1428 case ERR_SPDY_PING_FAILED: | 1472 case ERR_SPDY_PING_FAILED: |
| 1429 case ERR_SPDY_SERVER_REFUSED_STREAM: | 1473 case ERR_SPDY_SERVER_REFUSED_STREAM: |
| 1430 case ERR_QUIC_HANDSHAKE_FAILED: | 1474 case ERR_QUIC_HANDSHAKE_FAILED: |
| 1431 net_log_.AddEventWithNetErrorCode( | 1475 net_log_.AddEventWithNetErrorCode( |
| 1432 NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, error); | 1476 NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, error); |
| 1433 ResetConnectionAndRequestForResend(); | 1477 ResetConnectionAndRequestForResend(); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1455 request_headers_.Clear(); | 1499 request_headers_.Clear(); |
| 1456 response_ = HttpResponseInfo(); | 1500 response_ = HttpResponseInfo(); |
| 1457 establishing_tunnel_ = false; | 1501 establishing_tunnel_ = false; |
| 1458 } | 1502 } |
| 1459 | 1503 |
| 1460 HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const { | 1504 HttpResponseHeaders* HttpNetworkTransaction::GetResponseHeaders() const { |
| 1461 return response_.headers.get(); | 1505 return response_.headers.get(); |
| 1462 } | 1506 } |
| 1463 | 1507 |
| 1464 bool HttpNetworkTransaction::ShouldResendRequest() const { | 1508 bool HttpNetworkTransaction::ShouldResendRequest() const { |
| 1465 bool connection_is_proven = stream_->IsConnectionReused(); | 1509 if (retry_attempt_ > kNumRetries) |
| 1466 bool has_received_headers = GetResponseHeaders() != NULL; | 1510 return false; |
| 1467 | 1511 |
| 1468 // NOTE: we resend a request only if we reused a keep-alive connection. | 1512 if (headers_valid_) { |
|
mmenke
2014/07/23 20:17:42
If there a reason the old GetResponseHeaders() !=
jonnyr
2014/07/25 13:41:59
Done.
| |
| 1469 // This automatically prevents an infinite resend loop because we'll run | 1513 // Do not attempt a retry on anything but GET request if headers are valid. |
|
rvargas (doing something else)
2014/07/24 19:09:47
How do we know that nothing actually reached the s
jonnyr
2014/07/25 13:41:59
Right, this will have to be removed.
| |
| 1470 // out of the cached keep-alive connections eventually. | 1514 if (request_->method != "GET") |
| 1471 if (connection_is_proven && !has_received_headers) | 1515 return false; |
| 1472 return true; | 1516 |
| 1473 return false; | 1517 TimeDelta time_delta = base::TimeTicks::Now() - send_start_time_; |
| 1518 if (time_delta.InSeconds() > 30) | |
| 1519 return true; | |
| 1520 | |
| 1521 // Do not retry automatically if resource is larger than 1 Mb until byte | |
| 1522 // range support is enabled. This is temporary. | |
| 1523 if (response_.headers->GetContentLength() > 1000000) | |
|
rvargas (doing something else)
2014/07/24 19:09:47
Seems like this should go before the 30 seconds ru
jonnyr
2014/07/25 13:41:59
Done.
| |
| 1524 return false; | |
| 1525 | |
| 1526 // If etag or last-modified is set we can always retry since the response | |
| 1527 // can be verified. | |
| 1528 if (response_.headers->HasHeader("etag") || | |
|
rvargas (doing something else)
2014/07/24 19:09:47
use HasStrongValidators()
jonnyr
2014/07/25 13:41:59
Done.
| |
| 1529 response_.headers->HasHeader("Last-Modified")) { | |
| 1530 return true; | |
| 1531 } | |
| 1532 | |
| 1533 if (response_.headers->HasHeaderValue("cache-control", "no-cache") || | |
|
rvargas (doing something else)
2014/07/24 19:09:47
why fail if no-cache or must-revalidate?
jonnyr
2014/07/25 13:41:59
What I am trying to avoid is that we glue together
rvargas (doing something else)
2014/07/26 00:30:33
hmm... I don't think it is safe to remove the hash
| |
| 1534 response_.headers->HasHeaderValue("cache-control", "no-store") || | |
| 1535 response_.headers->HasHeaderValue("cache-control", "must-revalidate") || | |
| 1536 response_.headers->HasHeaderValue("pragma", "no-cache")) { | |
| 1537 return false; | |
| 1538 } | |
| 1539 | |
| 1540 if (response_.headers->GetMaxAgeValue(&time_delta)) | |
| 1541 return time_delta.InSeconds() > 60; | |
| 1542 | |
| 1543 // If there is no Date header, then assume that the server response was | |
| 1544 // generated at the time when we received the response, hence do not retry. | |
|
rvargas (doing something else)
2014/07/24 19:09:48
why not? If it actually differs, we'll catch that
jonnyr
2014/07/25 13:41:59
The intention is to remove the hash.
| |
| 1545 Time date_value; | |
| 1546 if (!response_.headers->GetDateValue(&date_value)) | |
| 1547 return false; | |
| 1548 | |
| 1549 Time expires_value; | |
| 1550 if (response_.headers->GetExpiresValue(&expires_value)) { | |
| 1551 time_delta = expires_value - date_value; | |
| 1552 if (time_delta.InSeconds() > 60) | |
| 1553 return true; | |
| 1554 } | |
|
rvargas (doing something else)
2014/07/24 19:09:47
Most of this logic should probably be moved to a m
jonnyr
2014/07/25 13:41:59
That I can do. Do you think the overall strategy a
rvargas (doing something else)
2014/07/26 00:30:33
Yeah, I think that avoid merging by using a hash m
| |
| 1555 return false; | |
| 1556 } | |
| 1557 return true; | |
|
mmenke
2014/07/23 20:17:42
Out of paranoia, think we should keep the only ret
jonnyr
2014/07/25 13:41:59
Agreed.
| |
| 1474 } | 1558 } |
| 1475 | 1559 |
| 1476 void HttpNetworkTransaction::ResetConnectionAndRequestForResend() { | 1560 void HttpNetworkTransaction::ResetConnectionAndRequestForResend() { |
| 1561 // We need to clear request_headers_ because it contains the real request | |
| 1562 // headers, but we may need to resend the CONNECT request first to recreate | |
| 1563 // the SSL tunnel. | |
| 1564 request_headers_.Clear(); | |
| 1565 headers_valid_ = false; | |
| 1566 | |
| 1567 if (stream_) { | |
| 1568 total_received_bytes_ += stream_->GetTotalReceivedBytes(); | |
| 1569 if (stream_->GetReceivedBodyLength() > offset_) { | |
| 1570 offset_ = stream_->GetReceivedBodyLength(); | |
| 1571 stream_->GetHash(hash_, sizeof(hash_)); | |
| 1572 } | |
| 1573 } | |
| 1574 | |
| 1575 HttpResponseHeaders* headers = GetResponseHeaders(); | |
| 1576 if (offset_ && headers) { | |
| 1577 previous_content_length_ = headers->GetContentLength(); | |
| 1578 headers->EnumerateHeader(NULL, "last-modified", | |
| 1579 &previous_last_modified_); | |
| 1580 if (headers->GetHttpVersion() >= HttpVersion(1, 1)) | |
| 1581 headers->EnumerateHeader(NULL, "etag", &previous_etag_); | |
| 1582 | |
| 1583 // Disable until we have statistics that show that retrying does not | |
| 1584 // result in too many ERR_RETRY_HASH_MISMATCH. | |
| 1585 if (0 && previous_content_length_ && | |
| 1586 headers->HasHeaderValue("Accept-Ranges", "bytes")) { | |
| 1587 // Try resending using a range request if supported. | |
| 1588 request_headers_.SetHeader(HttpRequestHeaders::kRange, | |
| 1589 "bytes=" + base::Uint64ToString(offset_) + "-"); | |
| 1590 if (!previous_last_modified_.empty()) | |
| 1591 request_headers_.SetHeader("If-Unmodified-Since", | |
| 1592 previous_last_modified_); | |
| 1593 if (!previous_etag_.empty()) | |
|
rvargas (doing something else)
2014/07/24 19:09:47
I suggest checking this one before last-modified a
jonnyr
2014/07/25 13:41:59
Done.
| |
| 1594 request_headers_.SetHeader("If-Match", previous_etag_); | |
| 1595 } | |
| 1596 } | |
| 1597 | |
| 1598 response_ = HttpResponseInfo(); | |
| 1599 establishing_tunnel_ = false; | |
| 1477 if (stream_.get()) { | 1600 if (stream_.get()) { |
| 1478 stream_->Close(true); | 1601 stream_->Close(true); |
| 1479 stream_.reset(); | 1602 stream_.reset(); |
| 1480 } | 1603 } |
| 1481 | |
| 1482 // We need to clear request_headers_ because it contains the real request | |
| 1483 // headers, but we may need to resend the CONNECT request first to recreate | |
| 1484 // the SSL tunnel. | |
| 1485 request_headers_.Clear(); | |
| 1486 next_state_ = STATE_CREATE_STREAM; // Resend the request. | 1604 next_state_ = STATE_CREATE_STREAM; // Resend the request. |
| 1487 } | 1605 } |
| 1488 | 1606 |
| 1489 bool HttpNetworkTransaction::ShouldApplyProxyAuth() const { | 1607 bool HttpNetworkTransaction::ShouldApplyProxyAuth() const { |
| 1490 return !is_https_request() && | 1608 return !is_https_request() && |
| 1491 (proxy_info_.is_https() || proxy_info_.is_http()); | 1609 (proxy_info_.is_https() || proxy_info_.is_http()); |
| 1492 } | 1610 } |
| 1493 | 1611 |
| 1494 bool HttpNetworkTransaction::ShouldApplyServerAuth() const { | 1612 bool HttpNetworkTransaction::ShouldApplyServerAuth() const { |
| 1495 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA); | 1613 return !(request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1584 description = base::StringPrintf("Unknown state 0x%08X (%u)", state, | 1702 description = base::StringPrintf("Unknown state 0x%08X (%u)", state, |
| 1585 state); | 1703 state); |
| 1586 break; | 1704 break; |
| 1587 } | 1705 } |
| 1588 return description; | 1706 return description; |
| 1589 } | 1707 } |
| 1590 | 1708 |
| 1591 #undef STATE_CASE | 1709 #undef STATE_CASE |
| 1592 | 1710 |
| 1593 } // namespace net | 1711 } // namespace net |
| OLD | NEW |