OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 <stdarg.h> | 8 #include <stdarg.h> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
13 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
14 #include "base/files/file_path.h" | 14 #include "base/files/file_path.h" |
15 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
16 #include "base/json/json_writer.h" | 16 #include "base/json/json_writer.h" |
| 17 #include "base/logging.h" |
17 #include "base/memory/scoped_ptr.h" | 18 #include "base/memory/scoped_ptr.h" |
18 #include "base/memory/weak_ptr.h" | 19 #include "base/memory/weak_ptr.h" |
19 #include "base/run_loop.h" | 20 #include "base/run_loop.h" |
20 #include "base/strings/string_util.h" | 21 #include "base/strings/string_util.h" |
21 #include "base/strings/utf_string_conversions.h" | 22 #include "base/strings/utf_string_conversions.h" |
22 #include "base/test/test_file_util.h" | 23 #include "base/test/test_file_util.h" |
23 #include "net/base/auth.h" | 24 #include "net/base/auth.h" |
24 #include "net/base/capturing_net_log.h" | 25 #include "net/base/capturing_net_log.h" |
25 #include "net/base/chunked_upload_data_stream.h" | 26 #include "net/base/chunked_upload_data_stream.h" |
26 #include "net/base/completion_callback.h" | 27 #include "net/base/completion_callback.h" |
27 #include "net/base/elements_upload_data_stream.h" | 28 #include "net/base/elements_upload_data_stream.h" |
28 #include "net/base/load_timing_info.h" | 29 #include "net/base/load_timing_info.h" |
29 #include "net/base/load_timing_info_test_util.h" | 30 #include "net/base/load_timing_info_test_util.h" |
| 31 #include "net/base/net_errors.h" |
30 #include "net/base/net_log.h" | 32 #include "net/base/net_log.h" |
31 #include "net/base/net_log_unittest.h" | 33 #include "net/base/net_log_unittest.h" |
32 #include "net/base/request_priority.h" | 34 #include "net/base/request_priority.h" |
33 #include "net/base/test_completion_callback.h" | 35 #include "net/base/test_completion_callback.h" |
34 #include "net/base/test_data_directory.h" | 36 #include "net/base/test_data_directory.h" |
35 #include "net/base/upload_bytes_element_reader.h" | 37 #include "net/base/upload_bytes_element_reader.h" |
36 #include "net/base/upload_file_element_reader.h" | 38 #include "net/base/upload_file_element_reader.h" |
37 #include "net/cert/mock_cert_verifier.h" | 39 #include "net/cert/mock_cert_verifier.h" |
38 #include "net/dns/host_cache.h" | 40 #include "net/dns/host_cache.h" |
39 #include "net/dns/mock_host_resolver.h" | 41 #include "net/dns/mock_host_resolver.h" |
40 #include "net/http/http_auth_challenge_tokenizer.h" | 42 #include "net/http/http_auth_challenge_tokenizer.h" |
41 #include "net/http/http_auth_handler_digest.h" | 43 #include "net/http/http_auth_handler_digest.h" |
42 #include "net/http/http_auth_handler_mock.h" | 44 #include "net/http/http_auth_handler_mock.h" |
43 #include "net/http/http_auth_handler_ntlm.h" | 45 #include "net/http/http_auth_handler_ntlm.h" |
| 46 #include "net/http/http_basic_state.h" |
44 #include "net/http/http_basic_stream.h" | 47 #include "net/http/http_basic_stream.h" |
45 #include "net/http/http_network_session.h" | 48 #include "net/http/http_network_session.h" |
46 #include "net/http/http_network_session_peer.h" | 49 #include "net/http/http_network_session_peer.h" |
| 50 #include "net/http/http_request_headers.h" |
47 #include "net/http/http_server_properties_impl.h" | 51 #include "net/http/http_server_properties_impl.h" |
48 #include "net/http/http_stream.h" | 52 #include "net/http/http_stream.h" |
49 #include "net/http/http_stream_factory.h" | 53 #include "net/http/http_stream_factory.h" |
| 54 #include "net/http/http_stream_parser.h" |
50 #include "net/http/http_transaction_test_util.h" | 55 #include "net/http/http_transaction_test_util.h" |
51 #include "net/proxy/proxy_config_service_fixed.h" | 56 #include "net/proxy/proxy_config_service_fixed.h" |
52 #include "net/proxy/proxy_info.h" | 57 #include "net/proxy/proxy_info.h" |
53 #include "net/proxy/proxy_resolver.h" | 58 #include "net/proxy/proxy_resolver.h" |
54 #include "net/proxy/proxy_service.h" | 59 #include "net/proxy/proxy_service.h" |
55 #include "net/socket/client_socket_factory.h" | 60 #include "net/socket/client_socket_factory.h" |
56 #include "net/socket/client_socket_pool_manager.h" | 61 #include "net/socket/client_socket_pool_manager.h" |
57 #include "net/socket/mock_client_socket_pool_manager.h" | 62 #include "net/socket/mock_client_socket_pool_manager.h" |
58 #include "net/socket/next_proto.h" | 63 #include "net/socket/next_proto.h" |
59 #include "net/socket/socket_test_util.h" | 64 #include "net/socket/socket_test_util.h" |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 load_timing_info.send_start); | 208 load_timing_info.send_start); |
204 | 209 |
205 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end); | 210 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end); |
206 | 211 |
207 // Set at a higher level. | 212 // Set at a higher level. |
208 EXPECT_TRUE(load_timing_info.request_start_time.is_null()); | 213 EXPECT_TRUE(load_timing_info.request_start_time.is_null()); |
209 EXPECT_TRUE(load_timing_info.request_start.is_null()); | 214 EXPECT_TRUE(load_timing_info.request_start.is_null()); |
210 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); | 215 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); |
211 } | 216 } |
212 | 217 |
| 218 void AddWebSocketHeaders(net::HttpRequestHeaders* headers) { |
| 219 headers->SetHeader("Connection", "Upgrade"); |
| 220 headers->SetHeader("Upgrade", "websocket"); |
| 221 headers->SetHeader("Origin", "http://www.google.com"); |
| 222 headers->SetHeader("Sec-WebSocket-Version", "13"); |
| 223 headers->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ=="); |
| 224 } |
| 225 |
213 } // namespace | 226 } // namespace |
214 | 227 |
215 namespace net { | 228 namespace net { |
216 | 229 |
217 namespace { | 230 namespace { |
218 | 231 |
219 HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) { | 232 HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) { |
220 return SpdySessionDependencies::SpdyCreateSession(session_deps); | 233 return SpdySessionDependencies::SpdyCreateSession(session_deps); |
221 } | 234 } |
222 | 235 |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 CaptureGroupNameSSLSocketPool; | 570 CaptureGroupNameSSLSocketPool; |
558 | 571 |
559 template<typename ParentPool> | 572 template<typename ParentPool> |
560 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool( | 573 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool( |
561 HostResolver* host_resolver, | 574 HostResolver* host_resolver, |
562 CertVerifier* /* cert_verifier */) | 575 CertVerifier* /* cert_verifier */) |
563 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {} | 576 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {} |
564 | 577 |
565 template <> | 578 template <> |
566 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool( | 579 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool( |
567 HostResolver* host_resolver, | 580 HostResolver* /* host_resolver */, |
568 CertVerifier* /* cert_verifier */) | 581 CertVerifier* /* cert_verifier */) |
569 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) { | 582 : HttpProxyClientSocketPool(0, 0, NULL, NULL, NULL, NULL) { |
570 } | 583 } |
571 | 584 |
572 template <> | 585 template <> |
573 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool( | 586 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool( |
574 HostResolver* host_resolver, | 587 HostResolver* /* host_resolver */, |
575 CertVerifier* cert_verifier) | 588 CertVerifier* cert_verifier) |
576 : SSLClientSocketPool(0, | 589 : SSLClientSocketPool(0, |
577 0, | 590 0, |
578 NULL, | 591 NULL, |
579 host_resolver, | |
580 cert_verifier, | 592 cert_verifier, |
581 NULL, | 593 NULL, |
582 NULL, | 594 NULL, |
583 NULL, | 595 NULL, |
584 NULL, | 596 NULL, |
585 std::string(), | 597 std::string(), |
586 NULL, | 598 NULL, |
587 NULL, | 599 NULL, |
588 NULL, | 600 NULL, |
589 NULL, | 601 NULL, |
(...skipping 1245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1835 const char* const kStatusLines[] = { | 1847 const char* const kStatusLines[] = { |
1836 "HTTP/1.1 204 No Content", | 1848 "HTTP/1.1 204 No Content", |
1837 "HTTP/1.1 205 Reset Content", | 1849 "HTTP/1.1 205 Reset Content", |
1838 "HTTP/1.1 304 Not Modified", | 1850 "HTTP/1.1 304 Not Modified", |
1839 "HTTP/1.1 302 Found", | 1851 "HTTP/1.1 302 Found", |
1840 "HTTP/1.1 302 Found", | 1852 "HTTP/1.1 302 Found", |
1841 "HTTP/1.1 301 Moved Permanently", | 1853 "HTTP/1.1 301 Moved Permanently", |
1842 "HTTP/1.1 301 Moved Permanently", | 1854 "HTTP/1.1 301 Moved Permanently", |
1843 }; | 1855 }; |
1844 | 1856 |
1845 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines), | 1857 static_assert(kNumUnreadBodies == arraysize(kStatusLines), |
1846 forgot_to_update_kStatusLines); | 1858 "forgot to update kStatusLines"); |
1847 | 1859 |
1848 for (int i = 0; i < kNumUnreadBodies; ++i) | 1860 for (int i = 0; i < kNumUnreadBodies; ++i) |
1849 EXPECT_EQ(kStatusLines[i], response_lines[i]); | 1861 EXPECT_EQ(kStatusLines[i], response_lines[i]); |
1850 | 1862 |
1851 TestCompletionCallback callback; | 1863 TestCompletionCallback callback; |
1852 scoped_ptr<HttpTransaction> trans( | 1864 scoped_ptr<HttpTransaction> trans( |
1853 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); | 1865 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); |
1854 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); | 1866 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); |
1855 EXPECT_EQ(ERR_IO_PENDING, rv); | 1867 EXPECT_EQ(ERR_IO_PENDING, rv); |
1856 rv = callback.WaitForResult(); | 1868 rv = callback.WaitForResult(); |
(...skipping 10607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12464 ADD_FAILURE(); | 12476 ADD_FAILURE(); |
12465 return NULL; | 12477 return NULL; |
12466 } | 12478 } |
12467 | 12479 |
12468 private: | 12480 private: |
12469 base::WeakPtr<FakeStreamRequest> last_stream_request_; | 12481 base::WeakPtr<FakeStreamRequest> last_stream_request_; |
12470 | 12482 |
12471 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory); | 12483 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory); |
12472 }; | 12484 }; |
12473 | 12485 |
| 12486 // TODO(ricea): Maybe unify this with the one in |
| 12487 // url_request_http_job_unittest.cc ? |
| 12488 class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase { |
| 12489 public: |
| 12490 FakeWebSocketBasicHandshakeStream(scoped_ptr<ClientSocketHandle> connection, |
| 12491 bool using_proxy) |
| 12492 : state_(connection.release(), using_proxy) {} |
| 12493 |
| 12494 // Fake implementation of HttpStreamBase methods. |
| 12495 // This ends up being quite "real" because this object has to really send data |
| 12496 // on the mock socket. It might be easier to use the real implementation, but |
| 12497 // the fact that the WebSocket code is not compiled on iOS makes that |
| 12498 // difficult. |
| 12499 int InitializeStream(const HttpRequestInfo* request_info, |
| 12500 RequestPriority priority, |
| 12501 const BoundNetLog& net_log, |
| 12502 const CompletionCallback& callback) override { |
| 12503 state_.Initialize(request_info, priority, net_log, callback); |
| 12504 return OK; |
| 12505 } |
| 12506 |
| 12507 int SendRequest(const HttpRequestHeaders& request_headers, |
| 12508 HttpResponseInfo* response, |
| 12509 const CompletionCallback& callback) override { |
| 12510 return parser()->SendRequest(state_.GenerateRequestLine(), request_headers, |
| 12511 response, callback); |
| 12512 } |
| 12513 |
| 12514 int ReadResponseHeaders(const CompletionCallback& callback) override { |
| 12515 return parser()->ReadResponseHeaders(callback); |
| 12516 } |
| 12517 |
| 12518 int ReadResponseBody(IOBuffer* buf, |
| 12519 int buf_len, |
| 12520 const CompletionCallback& callback) override { |
| 12521 NOTREACHED(); |
| 12522 return ERR_IO_PENDING; |
| 12523 } |
| 12524 |
| 12525 void Close(bool not_reusable) override { |
| 12526 if (parser()) |
| 12527 parser()->Close(true); |
| 12528 } |
| 12529 |
| 12530 bool IsResponseBodyComplete() const override { |
| 12531 NOTREACHED(); |
| 12532 return false; |
| 12533 } |
| 12534 |
| 12535 bool CanFindEndOfResponse() const override { |
| 12536 return parser()->CanFindEndOfResponse(); |
| 12537 } |
| 12538 |
| 12539 bool IsConnectionReused() const override { |
| 12540 NOTREACHED(); |
| 12541 return false; |
| 12542 } |
| 12543 void SetConnectionReused() override { NOTREACHED(); } |
| 12544 |
| 12545 bool IsConnectionReusable() const override { |
| 12546 NOTREACHED(); |
| 12547 return false; |
| 12548 } |
| 12549 |
| 12550 int64 GetTotalReceivedBytes() const override { |
| 12551 NOTREACHED(); |
| 12552 return 0; |
| 12553 } |
| 12554 |
| 12555 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override { |
| 12556 NOTREACHED(); |
| 12557 return false; |
| 12558 } |
| 12559 |
| 12560 void GetSSLInfo(SSLInfo* ssl_info) override { NOTREACHED(); } |
| 12561 |
| 12562 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override { |
| 12563 NOTREACHED(); |
| 12564 } |
| 12565 |
| 12566 bool IsSpdyHttpStream() const override { |
| 12567 NOTREACHED(); |
| 12568 return false; |
| 12569 } |
| 12570 |
| 12571 void Drain(HttpNetworkSession* session) override { NOTREACHED(); } |
| 12572 |
| 12573 void SetPriority(RequestPriority priority) override { NOTREACHED(); } |
| 12574 |
| 12575 UploadProgress GetUploadProgress() const override { |
| 12576 NOTREACHED(); |
| 12577 return UploadProgress(); |
| 12578 } |
| 12579 |
| 12580 HttpStream* RenewStreamForAuth() override { |
| 12581 NOTREACHED(); |
| 12582 return nullptr; |
| 12583 } |
| 12584 |
| 12585 // Fake implementation of WebSocketHandshakeStreamBase method(s) |
| 12586 scoped_ptr<WebSocketStream> Upgrade() override { |
| 12587 NOTREACHED(); |
| 12588 return scoped_ptr<WebSocketStream>(); |
| 12589 } |
| 12590 |
| 12591 private: |
| 12592 HttpStreamParser* parser() const { return state_.parser(); } |
| 12593 HttpBasicState state_; |
| 12594 |
| 12595 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream); |
| 12596 }; |
| 12597 |
12474 // TODO(yhirano): Split this class out into a net/websockets file, if it is | 12598 // TODO(yhirano): Split this class out into a net/websockets file, if it is |
12475 // worth doing. | 12599 // worth doing. |
12476 class FakeWebSocketStreamCreateHelper : | 12600 class FakeWebSocketStreamCreateHelper : |
12477 public WebSocketHandshakeStreamBase::CreateHelper { | 12601 public WebSocketHandshakeStreamBase::CreateHelper { |
12478 public: | 12602 public: |
12479 WebSocketHandshakeStreamBase* CreateBasicStream( | 12603 WebSocketHandshakeStreamBase* CreateBasicStream( |
12480 scoped_ptr<ClientSocketHandle> connection, | 12604 scoped_ptr<ClientSocketHandle> connection, |
12481 bool using_proxy) override { | 12605 bool using_proxy) override { |
12482 NOTREACHED(); | 12606 return new FakeWebSocketBasicHandshakeStream(connection.Pass(), |
12483 return NULL; | 12607 using_proxy); |
12484 } | 12608 } |
12485 | 12609 |
12486 WebSocketHandshakeStreamBase* CreateSpdyStream( | 12610 WebSocketHandshakeStreamBase* CreateSpdyStream( |
12487 const base::WeakPtr<SpdySession>& session, | 12611 const base::WeakPtr<SpdySession>& session, |
12488 bool use_relative_url) override { | 12612 bool use_relative_url) override { |
12489 NOTREACHED(); | 12613 NOTREACHED(); |
12490 return NULL; | 12614 return NULL; |
12491 }; | 12615 }; |
12492 | 12616 |
12493 ~FakeWebSocketStreamCreateHelper() override {} | 12617 ~FakeWebSocketStreamCreateHelper() override {} |
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13247 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); | 13371 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); |
13248 EXPECT_EQ(ERR_IO_PENDING, rv); | 13372 EXPECT_EQ(ERR_IO_PENDING, rv); |
13249 | 13373 |
13250 rv = callback.WaitForResult(); | 13374 rv = callback.WaitForResult(); |
13251 EXPECT_EQ(ERR_CONNECTION_RESET, rv); | 13375 EXPECT_EQ(ERR_CONNECTION_RESET, rv); |
13252 | 13376 |
13253 const HttpResponseInfo* response = trans->GetResponseInfo(); | 13377 const HttpResponseInfo* response = trans->GetResponseInfo(); |
13254 EXPECT_TRUE(response == NULL); | 13378 EXPECT_TRUE(response == NULL); |
13255 } | 13379 } |
13256 | 13380 |
| 13381 // Verify that proxy headers are not sent to the destination server when |
| 13382 // establishing a tunnel for a secure WebSocket connection. |
| 13383 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) { |
| 13384 HttpRequestInfo request; |
| 13385 request.method = "GET"; |
| 13386 request.url = GURL("wss://www.google.com/"); |
| 13387 AddWebSocketHeaders(&request.extra_headers); |
| 13388 |
| 13389 // Configure against proxy server "myproxy:70". |
| 13390 session_deps_.proxy_service.reset( |
| 13391 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); |
| 13392 |
| 13393 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); |
| 13394 |
| 13395 // Since a proxy is configured, try to establish a tunnel. |
| 13396 MockWrite data_writes[] = { |
| 13397 MockWrite( |
| 13398 "CONNECT www.google.com:443 HTTP/1.1\r\n" |
| 13399 "Host: www.google.com\r\n" |
| 13400 "Proxy-Connection: keep-alive\r\n\r\n"), |
| 13401 |
| 13402 // After calling trans->RestartWithAuth(), this is the request we should |
| 13403 // be issuing -- the final header line contains the credentials. |
| 13404 MockWrite( |
| 13405 "CONNECT www.google.com:443 HTTP/1.1\r\n" |
| 13406 "Host: www.google.com\r\n" |
| 13407 "Proxy-Connection: keep-alive\r\n" |
| 13408 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), |
| 13409 |
| 13410 MockWrite( |
| 13411 "GET / HTTP/1.1\r\n" |
| 13412 "Host: www.google.com\r\n" |
| 13413 "Connection: Upgrade\r\n" |
| 13414 "Upgrade: websocket\r\n" |
| 13415 "Origin: http://www.google.com\r\n" |
| 13416 "Sec-WebSocket-Version: 13\r\n" |
| 13417 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"), |
| 13418 }; |
| 13419 |
| 13420 // The proxy responds to the connect with a 407, using a persistent |
| 13421 // connection. |
| 13422 MockRead data_reads[] = { |
| 13423 // No credentials. |
| 13424 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), |
| 13425 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), |
| 13426 MockRead("Proxy-Connection: close\r\n\r\n"), |
| 13427 |
| 13428 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), |
| 13429 |
| 13430 MockRead("HTTP/1.1 101 Switching Protocols\r\n"), |
| 13431 MockRead("Upgrade: websocket\r\n"), |
| 13432 MockRead("Connection: Upgrade\r\n"), |
| 13433 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"), |
| 13434 }; |
| 13435 |
| 13436 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes, |
| 13437 arraysize(data_writes)); |
| 13438 session_deps_.socket_factory->AddSocketDataProvider(&data); |
| 13439 SSLSocketDataProvider ssl(ASYNC, OK); |
| 13440 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); |
| 13441 |
| 13442 scoped_ptr<HttpTransaction> trans( |
| 13443 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); |
| 13444 FakeWebSocketStreamCreateHelper websocket_stream_create_helper; |
| 13445 trans->SetWebSocketHandshakeStreamCreateHelper( |
| 13446 &websocket_stream_create_helper); |
| 13447 |
| 13448 { |
| 13449 TestCompletionCallback callback; |
| 13450 |
| 13451 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); |
| 13452 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 13453 |
| 13454 rv = callback.WaitForResult(); |
| 13455 EXPECT_EQ(OK, rv); |
| 13456 } |
| 13457 |
| 13458 const HttpResponseInfo* response = trans->GetResponseInfo(); |
| 13459 ASSERT_TRUE(response); |
| 13460 ASSERT_TRUE(response->headers.get()); |
| 13461 EXPECT_EQ(407, response->headers->response_code()); |
| 13462 |
| 13463 { |
| 13464 TestCompletionCallback callback; |
| 13465 |
| 13466 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), |
| 13467 callback.callback()); |
| 13468 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 13469 |
| 13470 rv = callback.WaitForResult(); |
| 13471 EXPECT_EQ(OK, rv); |
| 13472 } |
| 13473 |
| 13474 response = trans->GetResponseInfo(); |
| 13475 ASSERT_TRUE(response); |
| 13476 ASSERT_TRUE(response->headers.get()); |
| 13477 |
| 13478 EXPECT_EQ(101, response->headers->response_code()); |
| 13479 |
| 13480 trans.reset(); |
| 13481 session->CloseAllConnections(); |
| 13482 } |
| 13483 |
| 13484 // Verify that proxy headers are not sent to the destination server when |
| 13485 // establishing a tunnel for an insecure WebSocket connection. |
| 13486 // This requires the authentication info to be injected into the auth cache |
| 13487 // due to crbug.com/395064 |
| 13488 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed. |
| 13489 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) { |
| 13490 HttpRequestInfo request; |
| 13491 request.method = "GET"; |
| 13492 request.url = GURL("ws://www.google.com/"); |
| 13493 AddWebSocketHeaders(&request.extra_headers); |
| 13494 |
| 13495 // Configure against proxy server "myproxy:70". |
| 13496 session_deps_.proxy_service.reset( |
| 13497 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); |
| 13498 |
| 13499 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); |
| 13500 |
| 13501 MockWrite data_writes[] = { |
| 13502 // Try to establish a tunnel for the WebSocket connection, with |
| 13503 // credentials. Because WebSockets have a separate set of socket pools, |
| 13504 // they cannot and will not use the same TCP/IP connection as the |
| 13505 // preflight HTTP request. |
| 13506 MockWrite( |
| 13507 "CONNECT www.google.com:80 HTTP/1.1\r\n" |
| 13508 "Host: www.google.com\r\n" |
| 13509 "Proxy-Connection: keep-alive\r\n" |
| 13510 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), |
| 13511 |
| 13512 MockWrite( |
| 13513 "GET / HTTP/1.1\r\n" |
| 13514 "Host: www.google.com\r\n" |
| 13515 "Connection: Upgrade\r\n" |
| 13516 "Upgrade: websocket\r\n" |
| 13517 "Origin: http://www.google.com\r\n" |
| 13518 "Sec-WebSocket-Version: 13\r\n" |
| 13519 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"), |
| 13520 }; |
| 13521 |
| 13522 MockRead data_reads[] = { |
| 13523 // HTTP CONNECT with credentials. |
| 13524 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), |
| 13525 |
| 13526 // WebSocket connection established inside tunnel. |
| 13527 MockRead("HTTP/1.1 101 Switching Protocols\r\n"), |
| 13528 MockRead("Upgrade: websocket\r\n"), |
| 13529 MockRead("Connection: Upgrade\r\n"), |
| 13530 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"), |
| 13531 }; |
| 13532 |
| 13533 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes, |
| 13534 arraysize(data_writes)); |
| 13535 session_deps_.socket_factory->AddSocketDataProvider(&data); |
| 13536 |
| 13537 session->http_auth_cache()->Add( |
| 13538 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, |
| 13539 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/"); |
| 13540 |
| 13541 scoped_ptr<HttpTransaction> trans( |
| 13542 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); |
| 13543 FakeWebSocketStreamCreateHelper websocket_stream_create_helper; |
| 13544 trans->SetWebSocketHandshakeStreamCreateHelper( |
| 13545 &websocket_stream_create_helper); |
| 13546 |
| 13547 TestCompletionCallback callback; |
| 13548 |
| 13549 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); |
| 13550 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 13551 |
| 13552 rv = callback.WaitForResult(); |
| 13553 EXPECT_EQ(OK, rv); |
| 13554 |
| 13555 const HttpResponseInfo* response = trans->GetResponseInfo(); |
| 13556 ASSERT_TRUE(response); |
| 13557 ASSERT_TRUE(response->headers.get()); |
| 13558 |
| 13559 EXPECT_EQ(101, response->headers->response_code()); |
| 13560 |
| 13561 trans.reset(); |
| 13562 session->CloseAllConnections(); |
| 13563 } |
| 13564 |
13257 } // namespace net | 13565 } // namespace net |
OLD | NEW |