OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 <math.h> // ceil | 7 #include <math.h> // ceil |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
(...skipping 1308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1319 | 1319 |
1320 rv = callback2.WaitForResult(); | 1320 rv = callback2.WaitForResult(); |
1321 EXPECT_EQ(OK, rv); | 1321 EXPECT_EQ(OK, rv); |
1322 | 1322 |
1323 response = trans->GetResponseInfo(); | 1323 response = trans->GetResponseInfo(); |
1324 ASSERT_FALSE(response == NULL); | 1324 ASSERT_FALSE(response == NULL); |
1325 EXPECT_TRUE(response->auth_challenge.get() == NULL); | 1325 EXPECT_TRUE(response->auth_challenge.get() == NULL); |
1326 EXPECT_EQ(100, response->headers->GetContentLength()); | 1326 EXPECT_EQ(100, response->headers->GetContentLength()); |
1327 } | 1327 } |
1328 | 1328 |
| 1329 // Test the request-challenge-retry sequence for basic auth, over a connection |
| 1330 // that requires a restart when setting up an SSL tunnel. |
| 1331 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) { |
| 1332 // Configure against proxy server "myproxy:70". |
| 1333 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70")); |
| 1334 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); |
| 1335 session_deps.net_log = log.bound().net_log(); |
| 1336 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); |
| 1337 |
| 1338 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); |
| 1339 |
| 1340 HttpRequestInfo request; |
| 1341 request.method = "GET"; |
| 1342 request.url = GURL("https://www.google.com/"); |
| 1343 // when the no authentication data flag is set. |
| 1344 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; |
| 1345 |
| 1346 // Since we have proxy, should try to establish tunnel. |
| 1347 MockWrite data_writes1[] = { |
| 1348 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" |
| 1349 "Host: www.google.com\r\n" |
| 1350 "Proxy-Connection: keep-alive\r\n\r\n"), |
| 1351 |
| 1352 // After calling trans->RestartWithAuth(), this is the request we should |
| 1353 // be issuing -- the final header line contains the credentials. |
| 1354 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" |
| 1355 "Host: www.google.com\r\n" |
| 1356 "Proxy-Connection: keep-alive\r\n" |
| 1357 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"), |
| 1358 |
| 1359 MockWrite("GET / HTTP/1.1\r\n" |
| 1360 "Host: www.google.com\r\n" |
| 1361 "Connection: keep-alive\r\n\r\n"), |
| 1362 }; |
| 1363 |
| 1364 // The proxy responds to the connect with a 407, using a persistent |
| 1365 // connection. |
| 1366 MockRead data_reads1[] = { |
| 1367 // No credentials. |
| 1368 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), |
| 1369 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), |
| 1370 MockRead("Proxy-Connection: close\r\n\r\n"), |
| 1371 |
| 1372 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), |
| 1373 |
| 1374 MockRead("HTTP/1.1 200 OK\r\n"), |
| 1375 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), |
| 1376 MockRead("Content-Length: 100\r\n\r\n"), |
| 1377 MockRead(false, OK), |
| 1378 }; |
| 1379 |
| 1380 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), |
| 1381 data_writes1, arraysize(data_writes1)); |
| 1382 session_deps.socket_factory.AddSocketDataProvider(&data1); |
| 1383 SSLSocketDataProvider ssl(true, OK); |
| 1384 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); |
| 1385 |
| 1386 TestCompletionCallback callback1; |
| 1387 |
| 1388 int rv = trans->Start(&request, &callback1, log.bound()); |
| 1389 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 1390 |
| 1391 rv = callback1.WaitForResult(); |
| 1392 EXPECT_EQ(OK, rv); |
| 1393 size_t pos = ExpectLogContainsSomewhere( |
| 1394 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, |
| 1395 NetLog::PHASE_NONE); |
| 1396 ExpectLogContainsSomewhere( |
| 1397 log.entries(), pos, |
| 1398 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, |
| 1399 NetLog::PHASE_NONE); |
| 1400 |
| 1401 const HttpResponseInfo* response = trans->GetResponseInfo(); |
| 1402 ASSERT_FALSE(response == NULL); |
| 1403 |
| 1404 EXPECT_EQ(407, response->headers->response_code()); |
| 1405 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); |
| 1406 |
| 1407 // The password prompt info should have been set in response->auth_challenge. |
| 1408 ASSERT_FALSE(response->auth_challenge.get() == NULL); |
| 1409 |
| 1410 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port); |
| 1411 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); |
| 1412 EXPECT_EQ(L"basic", response->auth_challenge->scheme); |
| 1413 |
| 1414 TestCompletionCallback callback2; |
| 1415 |
| 1416 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2); |
| 1417 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 1418 |
| 1419 rv = callback2.WaitForResult(); |
| 1420 EXPECT_EQ(OK, rv); |
| 1421 |
| 1422 response = trans->GetResponseInfo(); |
| 1423 ASSERT_FALSE(response == NULL); |
| 1424 |
| 1425 EXPECT_TRUE(response->headers->IsKeepAlive()); |
| 1426 EXPECT_EQ(200, response->headers->response_code()); |
| 1427 EXPECT_EQ(100, response->headers->GetContentLength()); |
| 1428 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); |
| 1429 |
| 1430 // The password prompt info should not be set. |
| 1431 EXPECT_TRUE(response->auth_challenge.get() == NULL); |
| 1432 } |
| 1433 |
1329 // Test the request-challenge-retry sequence for basic auth, over a keep-alive | 1434 // Test the request-challenge-retry sequence for basic auth, over a keep-alive |
1330 // proxy connection, when setting up an SSL tunnel. | 1435 // proxy connection, when setting up an SSL tunnel. |
1331 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) { | 1436 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) { |
1332 // Configure against proxy server "myproxy:70". | 1437 // Configure against proxy server "myproxy:70". |
1333 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70")); | 1438 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70")); |
1334 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); | 1439 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); |
1335 session_deps.net_log = log.bound().net_log(); | 1440 session_deps.net_log = log.bound().net_log(); |
1336 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); | 1441 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); |
1337 | 1442 |
1338 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); | 1443 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); |
(...skipping 4940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6279 request.load_flags = 0; | 6384 request.load_flags = 0; |
6280 | 6385 |
6281 // First round goes unauthenticated through the proxy. | 6386 // First round goes unauthenticated through the proxy. |
6282 MockWrite data_writes_1[] = { | 6387 MockWrite data_writes_1[] = { |
6283 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" | 6388 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" |
6284 "Host: www.google.com\r\n" | 6389 "Host: www.google.com\r\n" |
6285 "Proxy-Connection: keep-alive\r\n" | 6390 "Proxy-Connection: keep-alive\r\n" |
6286 "\r\n"), | 6391 "\r\n"), |
6287 }; | 6392 }; |
6288 MockRead data_reads_1[] = { | 6393 MockRead data_reads_1[] = { |
| 6394 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), |
6289 MockRead("HTTP/1.1 200 OK\r\n" | 6395 MockRead("HTTP/1.1 200 OK\r\n" |
6290 "Alternate-Protocol: 443:npn-spdy/2\r\n" | 6396 "Alternate-Protocol: 443:npn-spdy/2\r\n" |
6291 "Proxy-Connection: close\r\n" | 6397 "Proxy-Connection: close\r\n" |
6292 "\r\n"), | 6398 "\r\n"), |
6293 }; | 6399 }; |
6294 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1), | 6400 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1), |
6295 data_writes_1, arraysize(data_writes_1)); | 6401 data_writes_1, arraysize(data_writes_1)); |
6296 | 6402 |
6297 // Second round tries to tunnel to www.google.com due to the | 6403 // Second round tries to tunnel to www.google.com due to the |
6298 // Alternate-Protocol announcement in the first round. It fails due | 6404 // Alternate-Protocol announcement in the first round. It fails due |
6299 // to a proxy authentication challenge. | 6405 // to a proxy authentication challenge. |
| 6406 // After the failure, a tunnel is established to www.google.com using |
| 6407 // Proxy-Authorization headers. There is then a SPDY request round. |
| 6408 // |
| 6409 // NOTE: Despite the "Proxy-Connection: Close", these are done on the |
| 6410 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket |
| 6411 // does a Disconnect and Connect on the same socket, rather than trying |
| 6412 // to obtain a new one. |
| 6413 // |
| 6414 // NOTE: Originally, the proxy response to the second CONNECT request |
| 6415 // simply returned another 407 so the unit test could skip the SSL connection |
| 6416 // establishment and SPDY framing issues. Alas, the |
| 6417 // retry-http-when-alternate-protocol fails logic kicks in, which was more |
| 6418 // complicated to set up expectations for than the SPDY session. |
| 6419 |
| 6420 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |
| 6421 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 6422 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true)); |
| 6423 |
6300 MockWrite data_writes_2[] = { | 6424 MockWrite data_writes_2[] = { |
| 6425 // First connection attempt without Proxy-Authorization. |
6301 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" | 6426 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" |
6302 "Host: www.google.com\r\n" | 6427 "Host: www.google.com\r\n" |
6303 "Proxy-Connection: keep-alive\r\n" | 6428 "Proxy-Connection: keep-alive\r\n" |
6304 "\r\n"), | 6429 "\r\n"), |
6305 }; | |
6306 MockRead data_reads_2[] = { | |
6307 MockRead("HTTP/1.0 407 Unauthorized\r\n" | |
6308 "Proxy-Authenticate: Mock\r\n" | |
6309 "Proxy-Connection: close\r\n" | |
6310 "\r\n"), | |
6311 }; | |
6312 StaticSocketDataProvider data_2(data_reads_2, arraysize(data_reads_2), | |
6313 data_writes_2, arraysize(data_writes_2)); | |
6314 | 6430 |
6315 // Third round establishes a tunnel to www.google.com due to the | 6431 // Second connection attempt with Proxy-Authorization. |
6316 // Alternate-Protocol announcement in the first round, and does a SPDY | |
6317 // request round. | |
6318 // TODO(cbentzel): Originally, this just returned another 407 so the unit test | |
6319 // could skip the SSL connection establishment and SPDY framing issues. Alas, | |
6320 // the retry-http-when-alternate-protocol fails logic kicks in, which was more | |
6321 // complicated to set up expectations for than the SPDY session. | |
6322 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); | |
6323 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); | |
6324 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true)); | |
6325 | |
6326 MockWrite data_writes_3[] = { | |
6327 // TUNNEL connection established | |
6328 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" | 6432 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" |
6329 "Host: www.google.com\r\n" | 6433 "Host: www.google.com\r\n" |
6330 "Proxy-Connection: keep-alive\r\n" | 6434 "Proxy-Connection: keep-alive\r\n" |
6331 "Proxy-Authorization: auth_token\r\n" | 6435 "Proxy-Authorization: auth_token\r\n" |
6332 "\r\n"), | 6436 "\r\n"), |
| 6437 |
6333 // SPDY request | 6438 // SPDY request |
6334 CreateMockWrite(*req), // 3 | 6439 CreateMockWrite(*req), |
6335 }; | 6440 }; |
| 6441 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n" |
| 6442 "Proxy-Authenticate: Mock\r\n" |
| 6443 "Proxy-Connection: close\r\n" |
| 6444 "\r\n"); |
| 6445 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n"; |
| 6446 MockRead data_reads_2[] = { |
| 6447 // First connection attempt fails |
| 6448 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1), |
| 6449 MockRead(true, kRejectConnectResponse, |
| 6450 arraysize(kRejectConnectResponse) - 1, 1), |
6336 | 6451 |
6337 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n"; | 6452 // Second connection attempt passes |
6338 MockRead data_reads_3[] = { | 6453 MockRead(true, kAcceptConnectResponse, |
6339 // Proxy response | 6454 arraysize(kAcceptConnectResponse) -1, 4), |
6340 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), | 6455 |
6341 // SPDY response. | 6456 // SPDY response |
6342 CreateMockRead(*resp.get(), 4), | 6457 CreateMockRead(*resp.get(), 6), |
6343 CreateMockRead(*data.get(), 4), | 6458 CreateMockRead(*data.get(), 6), |
6344 MockRead(true, 0, 0, 4), | 6459 MockRead(true, 0, 0, 6), |
6345 }; | 6460 }; |
6346 scoped_refptr<OrderedSocketData> data_3( | 6461 scoped_refptr<OrderedSocketData> data_2( |
6347 new OrderedSocketData(data_reads_3, arraysize(data_reads_3), | 6462 new OrderedSocketData(data_reads_2, arraysize(data_reads_2), |
6348 data_writes_3, arraysize(data_writes_3))); | 6463 data_writes_2, arraysize(data_writes_2))); |
6349 | 6464 |
6350 SSLSocketDataProvider ssl(true, OK); | 6465 SSLSocketDataProvider ssl(true, OK); |
6351 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; | 6466 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; |
6352 ssl.next_proto = "spdy/2"; | 6467 ssl.next_proto = "spdy/2"; |
6353 ssl.was_npn_negotiated = true; | 6468 ssl.was_npn_negotiated = true; |
6354 | 6469 |
6355 session_deps.socket_factory.AddSocketDataProvider(&data_1); | 6470 session_deps.socket_factory.AddSocketDataProvider(&data_1); |
6356 session_deps.socket_factory.AddSocketDataProvider(&data_2); | 6471 session_deps.socket_factory.AddSocketDataProvider(data_2.get()); |
6357 session_deps.socket_factory.AddSocketDataProvider(data_3.get()); | |
6358 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); | 6472 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); |
6359 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); | 6473 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); |
6360 | 6474 |
6361 // First round should work and provide the Alternate-Protocol state. | 6475 // First round should work and provide the Alternate-Protocol state. |
6362 TestCompletionCallback callback_1; | 6476 TestCompletionCallback callback_1; |
6363 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session)); | 6477 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session)); |
6364 int rv = trans_1->Start(&request, &callback_1, BoundNetLog()); | 6478 int rv = trans_1->Start(&request, &callback_1, BoundNetLog()); |
6365 EXPECT_EQ(ERR_IO_PENDING, rv); | 6479 EXPECT_EQ(ERR_IO_PENDING, rv); |
6366 EXPECT_EQ(OK, callback_1.WaitForResult()); | 6480 EXPECT_EQ(OK, callback_1.WaitForResult()); |
6367 | 6481 |
(...skipping 17 matching lines...) Expand all Loading... |
6385 // what this test is all about. Make sure it happens correctly. | 6499 // what this test is all about. Make sure it happens correctly. |
6386 const GURL& request_url = auth_handler->request_url(); | 6500 const GURL& request_url = auth_handler->request_url(); |
6387 EXPECT_EQ("https", request_url.scheme()); | 6501 EXPECT_EQ("https", request_url.scheme()); |
6388 EXPECT_EQ("www.google.com", request_url.host()); | 6502 EXPECT_EQ("www.google.com", request_url.host()); |
6389 | 6503 |
6390 HttpNetworkTransaction::SetNextProtos(""); | 6504 HttpNetworkTransaction::SetNextProtos(""); |
6391 HttpNetworkTransaction::SetUseAlternateProtocols(false); | 6505 HttpNetworkTransaction::SetUseAlternateProtocols(false); |
6392 } | 6506 } |
6393 | 6507 |
6394 } // namespace net | 6508 } // namespace net |
OLD | NEW |