shill: Support CONNECT HTTP method in proxy
This will allow HTTPS requests to be proxied.
BUG=chromium-os:24220
TEST=New unit tests +
manual "curl -v -x localhost:xxx https://www.google.com" test
Change-Id: Ibdec3536edb97018f6a7e7545025dd792998e7b0
Reviewed-on: https://gerrit.chromium.org/gerrit/13955
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Reviewed-by: Thieu Le <thieule@chromium.org>
Commit-Ready: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/http_proxy_unittest.cc b/http_proxy_unittest.cc
index d7f4ddb..ae4cd75 100644
--- a/http_proxy_unittest.cc
+++ b/http_proxy_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -41,13 +41,17 @@
namespace shill {
namespace {
-const char kBadHeader[] = "BLAH\r\n";
+const char kBadHeaderMissingURL[] = "BLAH\r\n";
+const char kBadHeaderMissingVersion[] = "BLAH http://hostname\r\n";
const char kBadHostnameLine[] = "GET HTTP/1.1 http://hostname\r\n";
const char kBasicGetHeader[] = "GET / HTTP/1.1\r\n";
const char kBasicGetHeaderWithURL[] =
"GET http://www.chromium.org/ HTTP/1.1\r\n";
const char kBasicGetHeaderWithURLNoTrailingSlash[] =
"GET http://www.chromium.org HTTP/1.1\r\n";
+const char kConnectQuery[] =
+ "CONNECT 10.10.10.10:443 HTTP/1.1\r\n"
+ "Host: 10.10.10.10:443\r\n\r\n";
const char kQueryTemplate[] = "GET %s HTTP/%s\r\n%s"
"User-Agent: Mozilla/5.0 (X11; CrOS i686 1299.0.2011) "
"AppleWebKit/535.8 (KHTML, like Gecko) Chrome/17.0.936.0 Safari/535.8\r\n"
@@ -75,6 +79,7 @@
const int kServerFD = 10204;
const int kClientFD = 10205;
const int kServerPort = 40506;
+const int kConnectPort = 443;
} // namespace {}
MATCHER_P(IsIPAddress, address, "") {
@@ -243,13 +248,16 @@
void ExpectTransactionTimeout() {
ExpectTimeout(HTTPProxy::kTransactionTimeoutSeconds);
}
+ void ExpectInClientResponse(const string &response_data) {
+ string server_data(reinterpret_cast<char *>(proxy_.server_data_.GetData()),
+ proxy_.server_data_.GetLength());
+ EXPECT_NE(string::npos, server_data.find(response_data));
+ }
void ExpectClientError(int code, const string &error) {
EXPECT_EQ(HTTPProxy::kStateFlushResponse, GetProxyState());
string status_line = StringPrintf("HTTP/1.1 %d ERROR", code);
- string server_data(reinterpret_cast<char *>(proxy_.server_data_.GetData()),
- proxy_.server_data_.GetLength());
- EXPECT_NE(string::npos, server_data.find(status_line));
- EXPECT_NE(string::npos, server_data.find(error));
+ ExpectInClientResponse(status_line);
+ ExpectInClientResponse(error);
}
void ExpectClientInternalError() {
ExpectClientError(500, HTTPProxy::kInternalErrorMsg);
@@ -281,12 +289,15 @@
.WillOnce(DoAll(Invoke(this, &HTTPProxyTest::InvokeSyncConnect),
Return(true)));
}
- void ExpectClientResult() {
+ void ExpectClientData() {
EXPECT_CALL(dispatcher(),
CreateReadyHandler(kClientFD,
IOHandler::kModeOutput,
proxy_.write_client_callback_.get()))
.WillOnce(ReturnNew<IOHandler>());
+ }
+ void ExpectClientResult() {
+ ExpectClientData();
ExpectInputTimeout();
}
void ExpectServerInput() {
@@ -527,10 +538,17 @@
EXPECT_EQ(HTTPProxy::kStateWaitConnection, GetProxyState());
}
-TEST_F(HTTPProxyTest, ReadBadFirstLine) {
+TEST_F(HTTPProxyTest, ReadMissingURL) {
SetupClient();
ExpectClientResult();
- ReadFromClient(kBadHeader);
+ ReadFromClient(kBadHeaderMissingURL);
+ ExpectClientError(501, "Server could not parse HTTP method");
+}
+
+TEST_F(HTTPProxyTest, ReadMissingVersion) {
+ SetupClient();
+ ExpectClientResult();
+ ReadFromClient(kBadHeaderMissingVersion);
ExpectClientError(501, "Server only accepts HTTP/1.x requests");
}
@@ -680,6 +698,18 @@
SetupConnectComplete();
}
+TEST_F(HTTPProxyTest, HTTPConnectMethod) {
+ SetupClient();
+ ExpectAsyncConnect(kServerAddress, kConnectPort, true);
+ ExpectConnectTimeout();
+ ExpectRouteRequest();
+ ReadFromClient(kConnectQuery);
+ ExpectRepeatedInputTimeout();
+ ExpectClientData();
+ OnConnectCompletion(true, kServerFD);
+ ExpectInClientResponse("HTTP/1.1 200 OK\r\n\r\n");
+}
+
TEST_F(HTTPProxyTest, TunnelData) {
SetupConnectComplete();