Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: net/http/http_network_transaction_unittest.cc

Issue 21433: Perform HTTP authentication over a keep-alive connection.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Last upload before checkin Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/http/http_network_transaction.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « net/http/http_network_transaction.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698