OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 <math.h> // ceil | 5 #include <math.h> // ceil |
6 | 6 |
7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
8 #include "net/base/client_socket_factory.h" | 8 #include "net/base/client_socket_factory.h" |
9 #include "net/base/test_completion_callback.h" | 9 #include "net/base/test_completion_callback.h" |
10 #include "net/base/upload_data.h" | 10 #include "net/base/upload_data.h" |
(...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
704 | 704 |
705 rv = callback2.WaitForResult(); | 705 rv = callback2.WaitForResult(); |
706 EXPECT_EQ(net::OK, rv); | 706 EXPECT_EQ(net::OK, rv); |
707 | 707 |
708 response = trans->GetResponseInfo(); | 708 response = trans->GetResponseInfo(); |
709 EXPECT_FALSE(response == NULL); | 709 EXPECT_FALSE(response == NULL); |
710 EXPECT_TRUE(response->auth_challenge.get() == NULL); | 710 EXPECT_TRUE(response->auth_challenge.get() == NULL); |
711 EXPECT_EQ(100, response->headers->GetContentLength()); | 711 EXPECT_EQ(100, response->headers->GetContentLength()); |
712 } | 712 } |
713 | 713 |
| 714 // Test the request-challenge-retry sequence for basic auth, over a keep-alive |
| 715 // connection. |
| 716 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) { |
| 717 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService()); |
| 718 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction( |
| 719 CreateSession(proxy_service.get()), &mock_socket_factory)); |
| 720 |
| 721 net::HttpRequestInfo request; |
| 722 request.method = "GET"; |
| 723 request.url = GURL("http://www.google.com/"); |
| 724 request.load_flags = 0; |
| 725 |
| 726 MockWrite data_writes1[] = { |
| 727 MockWrite("GET / HTTP/1.1\r\n" |
| 728 "Host: www.google.com\r\n" |
| 729 "Connection: keep-alive\r\n\r\n"), |
| 730 |
| 731 // After calling trans->RestartWithAuth(), this is the request we should |
| 732 // be issuing -- the final header line contains the credentials. |
| 733 MockWrite("GET / HTTP/1.1\r\n" |
| 734 "Host: www.google.com\r\n" |
| 735 "Connection: keep-alive\r\n" |
| 736 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), |
| 737 }; |
| 738 |
| 739 MockRead data_reads1[] = { |
| 740 MockRead("HTTP/1.1 401 Unauthorized\r\n"), |
| 741 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), |
| 742 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), |
| 743 MockRead("Content-Length: 14\r\n\r\n"), |
| 744 MockRead("Unauthorized\r\n"), |
| 745 |
| 746 // Lastly, the server responds with the actual content. |
| 747 MockRead("HTTP/1.1 200 OK\r\n"), |
| 748 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), |
| 749 MockRead("Content-Length: 100\r\n\r\n"), |
| 750 MockRead(false, net::OK), |
| 751 }; |
| 752 |
| 753 MockSocket data1; |
| 754 data1.reads = data_reads1; |
| 755 data1.writes = data_writes1; |
| 756 mock_sockets[0] = &data1; |
| 757 mock_sockets[1] = NULL; |
| 758 |
| 759 TestCompletionCallback callback1; |
| 760 |
| 761 int rv = trans->Start(&request, &callback1); |
| 762 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 763 |
| 764 rv = callback1.WaitForResult(); |
| 765 EXPECT_EQ(net::OK, rv); |
| 766 |
| 767 const net::HttpResponseInfo* response = trans->GetResponseInfo(); |
| 768 EXPECT_FALSE(response == NULL); |
| 769 |
| 770 // The password prompt info should have been set in response->auth_challenge. |
| 771 EXPECT_FALSE(response->auth_challenge.get() == NULL); |
| 772 |
| 773 // TODO(eroman): this should really include the effective port (80) |
| 774 EXPECT_EQ(L"www.google.com", response->auth_challenge->host); |
| 775 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); |
| 776 EXPECT_EQ(L"basic", response->auth_challenge->scheme); |
| 777 |
| 778 TestCompletionCallback callback2; |
| 779 |
| 780 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2); |
| 781 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 782 |
| 783 rv = callback2.WaitForResult(); |
| 784 EXPECT_EQ(net::OK, rv); |
| 785 |
| 786 response = trans->GetResponseInfo(); |
| 787 EXPECT_FALSE(response == NULL); |
| 788 EXPECT_TRUE(response->auth_challenge.get() == NULL); |
| 789 EXPECT_EQ(100, response->headers->GetContentLength()); |
| 790 } |
| 791 |
| 792 // Test the request-challenge-retry sequence for basic auth, over a keep-alive |
| 793 // connection and with no response body to drain. |
| 794 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) { |
| 795 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService()); |
| 796 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction( |
| 797 CreateSession(proxy_service.get()), &mock_socket_factory)); |
| 798 |
| 799 net::HttpRequestInfo request; |
| 800 request.method = "GET"; |
| 801 request.url = GURL("http://www.google.com/"); |
| 802 request.load_flags = 0; |
| 803 |
| 804 MockWrite data_writes1[] = { |
| 805 MockWrite("GET / HTTP/1.1\r\n" |
| 806 "Host: www.google.com\r\n" |
| 807 "Connection: keep-alive\r\n\r\n"), |
| 808 |
| 809 // After calling trans->RestartWithAuth(), this is the request we should |
| 810 // be issuing -- the final header line contains the credentials. |
| 811 MockWrite("GET / HTTP/1.1\r\n" |
| 812 "Host: www.google.com\r\n" |
| 813 "Connection: keep-alive\r\n" |
| 814 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), |
| 815 }; |
| 816 |
| 817 // Respond with 5 kb of response body. |
| 818 std::string large_body_string("Unauthorized"); |
| 819 large_body_string.append(5 * 1024, ' '); |
| 820 large_body_string.append("\r\n"); |
| 821 |
| 822 MockRead data_reads1[] = { |
| 823 MockRead("HTTP/1.1 401 Unauthorized\r\n"), |
| 824 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), |
| 825 MockRead("Content-Length: 0\r\n\r\n"), |
| 826 |
| 827 // Lastly, the server responds with the actual content. |
| 828 MockRead("HTTP/1.1 200 OK\r\n"), |
| 829 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), |
| 830 MockRead("Content-Length: 100\r\n\r\n"), |
| 831 MockRead(false, net::OK), |
| 832 }; |
| 833 |
| 834 MockSocket data1; |
| 835 data1.reads = data_reads1; |
| 836 data1.writes = data_writes1; |
| 837 mock_sockets[0] = &data1; |
| 838 mock_sockets[1] = NULL; |
| 839 |
| 840 TestCompletionCallback callback1; |
| 841 |
| 842 int rv = trans->Start(&request, &callback1); |
| 843 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 844 |
| 845 rv = callback1.WaitForResult(); |
| 846 EXPECT_EQ(net::OK, rv); |
| 847 |
| 848 const net::HttpResponseInfo* response = trans->GetResponseInfo(); |
| 849 EXPECT_FALSE(response == NULL); |
| 850 |
| 851 // The password prompt info should have been set in response->auth_challenge. |
| 852 EXPECT_FALSE(response->auth_challenge.get() == NULL); |
| 853 |
| 854 // TODO(eroman): this should really include the effective port (80) |
| 855 EXPECT_EQ(L"www.google.com", response->auth_challenge->host); |
| 856 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); |
| 857 EXPECT_EQ(L"basic", response->auth_challenge->scheme); |
| 858 |
| 859 TestCompletionCallback callback2; |
| 860 |
| 861 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2); |
| 862 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 863 |
| 864 rv = callback2.WaitForResult(); |
| 865 EXPECT_EQ(net::OK, rv); |
| 866 |
| 867 response = trans->GetResponseInfo(); |
| 868 EXPECT_FALSE(response == NULL); |
| 869 EXPECT_TRUE(response->auth_challenge.get() == NULL); |
| 870 EXPECT_EQ(100, response->headers->GetContentLength()); |
| 871 } |
| 872 |
| 873 // Test the request-challenge-retry sequence for basic auth, over a keep-alive |
| 874 // connection and with a large response body to drain. |
| 875 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) { |
| 876 scoped_ptr<net::ProxyService> proxy_service(CreateNullProxyService()); |
| 877 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction( |
| 878 CreateSession(proxy_service.get()), &mock_socket_factory)); |
| 879 |
| 880 net::HttpRequestInfo request; |
| 881 request.method = "GET"; |
| 882 request.url = GURL("http://www.google.com/"); |
| 883 request.load_flags = 0; |
| 884 |
| 885 MockWrite data_writes1[] = { |
| 886 MockWrite("GET / HTTP/1.1\r\n" |
| 887 "Host: www.google.com\r\n" |
| 888 "Connection: keep-alive\r\n\r\n"), |
| 889 |
| 890 // After calling trans->RestartWithAuth(), this is the request we should |
| 891 // be issuing -- the final header line contains the credentials. |
| 892 MockWrite("GET / HTTP/1.1\r\n" |
| 893 "Host: www.google.com\r\n" |
| 894 "Connection: keep-alive\r\n" |
| 895 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), |
| 896 }; |
| 897 |
| 898 // Respond with 5 kb of response body. |
| 899 std::string large_body_string("Unauthorized"); |
| 900 large_body_string.append(5 * 1024, ' '); |
| 901 large_body_string.append("\r\n"); |
| 902 |
| 903 MockRead data_reads1[] = { |
| 904 MockRead("HTTP/1.1 401 Unauthorized\r\n"), |
| 905 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), |
| 906 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), |
| 907 // 5134 = 12 + 5 * 1024 + 2 |
| 908 MockRead("Content-Length: 5134\r\n\r\n"), |
| 909 MockRead(true, large_body_string.data(), large_body_string.size()), |
| 910 |
| 911 // Lastly, the server responds with the actual content. |
| 912 MockRead("HTTP/1.1 200 OK\r\n"), |
| 913 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), |
| 914 MockRead("Content-Length: 100\r\n\r\n"), |
| 915 MockRead(false, net::OK), |
| 916 }; |
| 917 |
| 918 MockSocket data1; |
| 919 data1.reads = data_reads1; |
| 920 data1.writes = data_writes1; |
| 921 mock_sockets[0] = &data1; |
| 922 mock_sockets[1] = NULL; |
| 923 |
| 924 TestCompletionCallback callback1; |
| 925 |
| 926 int rv = trans->Start(&request, &callback1); |
| 927 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 928 |
| 929 rv = callback1.WaitForResult(); |
| 930 EXPECT_EQ(net::OK, rv); |
| 931 |
| 932 const net::HttpResponseInfo* response = trans->GetResponseInfo(); |
| 933 EXPECT_FALSE(response == NULL); |
| 934 |
| 935 // The password prompt info should have been set in response->auth_challenge. |
| 936 EXPECT_FALSE(response->auth_challenge.get() == NULL); |
| 937 |
| 938 // TODO(eroman): this should really include the effective port (80) |
| 939 EXPECT_EQ(L"www.google.com", response->auth_challenge->host); |
| 940 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); |
| 941 EXPECT_EQ(L"basic", response->auth_challenge->scheme); |
| 942 |
| 943 TestCompletionCallback callback2; |
| 944 |
| 945 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2); |
| 946 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 947 |
| 948 rv = callback2.WaitForResult(); |
| 949 EXPECT_EQ(net::OK, rv); |
| 950 |
| 951 response = trans->GetResponseInfo(); |
| 952 EXPECT_FALSE(response == NULL); |
| 953 EXPECT_TRUE(response->auth_challenge.get() == NULL); |
| 954 EXPECT_EQ(100, response->headers->GetContentLength()); |
| 955 } |
| 956 |
| 957 // Test the request-challenge-retry sequence for basic auth, over a keep-alive |
| 958 // proxy connection, when setting up an SSL tunnel. |
| 959 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) { |
| 960 // Configure against proxy server "myproxy:70". |
| 961 scoped_ptr<net::ProxyService> proxy_service( |
| 962 CreateFixedProxyService("myproxy:70")); |
| 963 |
| 964 scoped_refptr<net::HttpNetworkSession> session( |
| 965 CreateSession(proxy_service.get())); |
| 966 |
| 967 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction( |
| 968 session.get(), &mock_socket_factory)); |
| 969 |
| 970 net::HttpRequestInfo request; |
| 971 request.method = "GET"; |
| 972 request.url = GURL("https://www.google.com/"); |
| 973 request.load_flags = 0; |
| 974 |
| 975 // Since we have proxy, should try to establish tunnel. |
| 976 MockWrite data_writes1[] = { |
| 977 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" |
| 978 "Host: www.google.com\r\n\r\n"), |
| 979 |
| 980 // After calling trans->RestartWithAuth(), this is the request we should |
| 981 // be issuing -- the final header line contains the credentials. |
| 982 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" |
| 983 "Host: www.google.com\r\n" |
| 984 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"), |
| 985 }; |
| 986 |
| 987 // The proxy responds to the connect with a 407, using a persistent |
| 988 // connection. |
| 989 MockRead data_reads1[] = { |
| 990 // No credentials. |
| 991 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), |
| 992 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), |
| 993 MockRead("Content-Length: 10\r\n\r\n"), |
| 994 MockRead("0123456789"), |
| 995 |
| 996 // Wrong credentials (wrong password). |
| 997 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), |
| 998 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), |
| 999 MockRead("Content-Length: 10\r\n\r\n"), |
| 1000 // No response body because the test stops reading here. |
| 1001 MockRead(false, net::ERR_UNEXPECTED), // Should not be reached. |
| 1002 }; |
| 1003 |
| 1004 MockSocket data1; |
| 1005 data1.writes = data_writes1; |
| 1006 data1.reads = data_reads1; |
| 1007 mock_sockets[0] = &data1; |
| 1008 mock_sockets[1] = NULL; |
| 1009 |
| 1010 TestCompletionCallback callback1; |
| 1011 |
| 1012 int rv = trans->Start(&request, &callback1); |
| 1013 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 1014 |
| 1015 rv = callback1.WaitForResult(); |
| 1016 EXPECT_EQ(net::OK, rv); |
| 1017 |
| 1018 const net::HttpResponseInfo* response = trans->GetResponseInfo(); |
| 1019 EXPECT_FALSE(response == NULL); |
| 1020 |
| 1021 EXPECT_TRUE(response->headers->IsKeepAlive()); |
| 1022 EXPECT_EQ(407, response->headers->response_code()); |
| 1023 EXPECT_EQ(10, response->headers->GetContentLength()); |
| 1024 EXPECT_TRUE(net::HttpVersion(1, 1) == response->headers->GetHttpVersion()); |
| 1025 |
| 1026 // The password prompt info should have been set in response->auth_challenge. |
| 1027 EXPECT_FALSE(response->auth_challenge.get() == NULL); |
| 1028 |
| 1029 // TODO(eroman): this should really include the effective port (80) |
| 1030 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host); |
| 1031 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); |
| 1032 EXPECT_EQ(L"basic", response->auth_challenge->scheme); |
| 1033 |
| 1034 TestCompletionCallback callback2; |
| 1035 |
| 1036 // Wrong password (should be "bar"). |
| 1037 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2); |
| 1038 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 1039 |
| 1040 rv = callback2.WaitForResult(); |
| 1041 EXPECT_EQ(net::OK, rv); |
| 1042 |
| 1043 response = trans->GetResponseInfo(); |
| 1044 EXPECT_FALSE(response == NULL); |
| 1045 |
| 1046 EXPECT_TRUE(response->headers->IsKeepAlive()); |
| 1047 EXPECT_EQ(407, response->headers->response_code()); |
| 1048 EXPECT_EQ(10, response->headers->GetContentLength()); |
| 1049 EXPECT_TRUE(net::HttpVersion(1, 1) == response->headers->GetHttpVersion()); |
| 1050 |
| 1051 // The password prompt info should have been set in response->auth_challenge. |
| 1052 EXPECT_FALSE(response->auth_challenge.get() == NULL); |
| 1053 |
| 1054 // TODO(eroman): this should really include the effective port (80) |
| 1055 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host); |
| 1056 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); |
| 1057 EXPECT_EQ(L"basic", response->auth_challenge->scheme); |
| 1058 } |
| 1059 |
714 // Test the flow when both the proxy server AND origin server require | 1060 // Test the flow when both the proxy server AND origin server require |
715 // authentication. Again, this uses basic auth for both since that is | 1061 // authentication. Again, this uses basic auth for both since that is |
716 // the simplest to mock. | 1062 // the simplest to mock. |
717 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) { | 1063 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) { |
718 scoped_ptr<net::ProxyService> proxy_service( | 1064 scoped_ptr<net::ProxyService> proxy_service( |
719 CreateFixedProxyService("myproxy:70")); | 1065 CreateFixedProxyService("myproxy:70")); |
720 | 1066 |
721 // Configure against proxy server "myproxy:70". | 1067 // Configure against proxy server "myproxy:70". |
722 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction( | 1068 scoped_ptr<net::HttpTransaction> trans(new net::HttpNetworkTransaction( |
723 CreateSession(proxy_service.get()), | 1069 CreateSession(proxy_service.get()), |
(...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1518 | 1864 |
1519 rv = callback2.WaitForResult(); | 1865 rv = callback2.WaitForResult(); |
1520 EXPECT_EQ(net::OK, rv); | 1866 EXPECT_EQ(net::OK, rv); |
1521 | 1867 |
1522 response = trans->GetResponseInfo(); | 1868 response = trans->GetResponseInfo(); |
1523 EXPECT_FALSE(response == NULL); | 1869 EXPECT_FALSE(response == NULL); |
1524 EXPECT_TRUE(response->auth_challenge.get() == NULL); | 1870 EXPECT_TRUE(response->auth_challenge.get() == NULL); |
1525 EXPECT_EQ(100, response->headers->GetContentLength()); | 1871 EXPECT_EQ(100, response->headers->GetContentLength()); |
1526 } | 1872 } |
1527 } | 1873 } |
OLD | NEW |