Fix infinite retry on 408
Fix issue where receiving HTTP response status 408 on
an HTTP/2 connection would cause us to retry infinitely.
We now only retry for HTTP/1.1 (and 0.9 and 1.0) but not
HTTP/2 and later.
Bug: 695225
Change-Id: I6a3c2c9447e4dde536fa7925306b41de9d4afb28
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1907188
Commit-Queue: David Schinazi <[email protected]>
Reviewed-by: Ryan Hamilton <[email protected]>
Auto-Submit: David Schinazi <[email protected]>
Cr-Commit-Position: refs/heads/master@{#713985}
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index 86a7ad6..cb603a4 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -705,17 +705,22 @@
void CreateSession() { return CreateSession(supported_versions_); }
- void CheckWasQuicResponse(HttpNetworkTransaction* trans) {
+ void CheckWasQuicResponse(HttpNetworkTransaction* trans,
+ const std::string& status_line) {
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != nullptr);
ASSERT_TRUE(response->headers.get() != nullptr);
- EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
+ EXPECT_EQ(status_line, response->headers->GetStatusLine());
EXPECT_TRUE(response->was_fetched_via_spdy);
EXPECT_TRUE(response->was_alpn_negotiated);
EXPECT_EQ(QuicHttpStream::ConnectionInfoFromQuicVersion(version_),
response->connection_info);
}
+ void CheckWasQuicResponse(HttpNetworkTransaction* trans) {
+ CheckWasQuicResponse(trans, "HTTP/1.1 200 OK");
+ }
+
void CheckResponsePort(HttpNetworkTransaction* trans, uint16_t port) {
const HttpResponseInfo* response = trans->GetResponseInfo();
ASSERT_TRUE(response != nullptr);
@@ -784,6 +789,11 @@
EXPECT_TRUE(trans.GetResponseInfo()->proxy_server.is_direct());
}
}
+ void SendRequestAndExpectQuicResponse(const std::string& expected,
+ const std::string& status_line) {
+ SendRequestAndExpectQuicResponseMaybeFromProxy(expected, false, 443,
+ status_line);
+ }
void SendRequestAndExpectQuicResponse(const std::string& expected) {
SendRequestAndExpectQuicResponseMaybeFromProxy(expected, false, 443);
@@ -1051,14 +1061,15 @@
void SendRequestAndExpectQuicResponseMaybeFromProxy(
const std::string& expected,
bool used_proxy,
- uint16_t port) {
+ uint16_t port,
+ const std::string& status_line) {
HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get());
HeadersHandler headers_handler;
trans.SetBeforeHeadersSentCallback(
base::Bind(&HeadersHandler::OnBeforeHeadersSent,
base::Unretained(&headers_handler)));
RunTransaction(&trans);
- CheckWasQuicResponse(&trans);
+ CheckWasQuicResponse(&trans, status_line);
CheckResponsePort(&trans, port);
CheckResponseData(&trans, expected);
EXPECT_EQ(used_proxy, headers_handler.was_proxied());
@@ -1068,6 +1079,14 @@
EXPECT_TRUE(trans.GetResponseInfo()->proxy_server.is_direct());
}
}
+
+ void SendRequestAndExpectQuicResponseMaybeFromProxy(
+ const std::string& expected,
+ bool used_proxy,
+ uint16_t port) {
+ SendRequestAndExpectQuicResponseMaybeFromProxy(expected, used_proxy, port,
+ "HTTP/1.1 200 OK");
+ }
};
INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
@@ -1492,6 +1511,43 @@
test_socket_performance_watcher_factory_.rtt_notification_received());
}
+// Regression test for https://crbug.com/695225
+TEST_P(QuicNetworkTransactionTest, 408Response) {
+ session_params_.quic_params.origins_to_force_quic_on.insert(HostPortPair());
+
+ AddQuicAlternateProtocolMapping(MockCryptoClientStream::CONFIRM_HANDSHAKE);
+
+ MockQuicData mock_quic_data(version_);
+ int packet_num = 1;
+ if (VersionUsesHttp3(version_.transport_version)) {
+ mock_quic_data.AddWrite(SYNCHRONOUS,
+ ConstructInitialSettingsPacket(packet_num++));
+ }
+ mock_quic_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructClientRequestHeadersPacket(
+ packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
+ true, GetRequestHeaders("GET", "https", "/")));
+ mock_quic_data.AddRead(
+ ASYNC, ConstructServerResponseHeadersPacket(
+ 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
+ GetResponseHeaders("408 Request Timeout")));
+ std::string header = ConstructDataHeader(6);
+ mock_quic_data.AddRead(
+ ASYNC, ConstructServerDataPacket(
+ 2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
+ header + "hello!"));
+ mock_quic_data.AddWrite(SYNCHRONOUS,
+ ConstructClientAckPacket(packet_num++, 2, 1, 1));
+ mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read
+
+ mock_quic_data.AddSocketDataToFactory(&socket_factory_);
+
+ CreateSession();
+
+ SendRequestAndExpectQuicResponse("hello!", "HTTP/1.1 408 Request Timeout");
+}
+
TEST_P(QuicNetworkTransactionTest, QuicProxy) {
session_params_.enable_quic = true;
proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(