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
3 // found in the LICENSE file.
4
5 #include "net/websockets/websocket_handshake_handler.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/basictypes.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "net/http/http_response_headers.h"
14 #include "net/http/http_util.h"
15 #include "url/gurl.h"
16
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace {
20
21 const char* const kCookieHeaders[] = {
22 "cookie", "cookie2"
23 };
24
25 const char* const kSetCookieHeaders[] = {
26 "set-cookie", "set-cookie2"
27 };
28
29 } // namespace
30
31 namespace net {
32
TEST(WebSocketHandshakeRequestHandlerTest,SimpleRequest)33 TEST(WebSocketHandshakeRequestHandlerTest, SimpleRequest) {
34 WebSocketHandshakeRequestHandler handler;
35
36 static const char kHandshakeRequestMessage[] =
37 "GET /demo HTTP/1.1\r\n"
38 "Host: example.com\r\n"
39 "Upgrade: websocket\r\n"
40 "Connection: Upgrade\r\n"
41 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
42 "Sec-WebSocket-Origin: http://example.com\r\n"
43 "Sec-WebSocket-Protocol: sample\r\n"
44 "Sec-WebSocket-Version: 13\r\n"
45 "\r\n";
46
47 EXPECT_TRUE(handler.ParseRequest(kHandshakeRequestMessage,
48 strlen(kHandshakeRequestMessage)));
49
50 handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
51
52 EXPECT_EQ(kHandshakeRequestMessage, handler.GetRawRequest());
53 }
54
TEST(WebSocketHandshakeRequestHandlerTest,ReplaceRequestCookies)55 TEST(WebSocketHandshakeRequestHandlerTest, ReplaceRequestCookies) {
56 WebSocketHandshakeRequestHandler handler;
57
58 static const char kHandshakeRequestMessage[] =
59 "GET /demo HTTP/1.1\r\n"
60 "Host: example.com\r\n"
61 "Upgrade: websocket\r\n"
62 "Connection: Upgrade\r\n"
63 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
64 "Sec-WebSocket-Origin: http://example.com\r\n"
65 "Sec-WebSocket-Protocol: sample\r\n"
66 "Sec-WebSocket-Version: 13\r\n"
67 "Cookie: WK-websocket-test=1\r\n"
68 "\r\n";
69
70 EXPECT_TRUE(handler.ParseRequest(kHandshakeRequestMessage,
71 strlen(kHandshakeRequestMessage)));
72
73 handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
74
75 handler.AppendHeaderIfMissing("Cookie",
76 "WK-websocket-test=1; "
77 "WK-websocket-test-httponly=1");
78
79 static const char kHandshakeRequestExpectedMessage[] =
80 "GET /demo HTTP/1.1\r\n"
81 "Host: example.com\r\n"
82 "Upgrade: websocket\r\n"
83 "Connection: Upgrade\r\n"
84 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
85 "Sec-WebSocket-Origin: http://example.com\r\n"
86 "Sec-WebSocket-Protocol: sample\r\n"
87 "Sec-WebSocket-Version: 13\r\n"
88 "Cookie: WK-websocket-test=1; WK-websocket-test-httponly=1\r\n"
89 "\r\n";
90
91 EXPECT_EQ(kHandshakeRequestExpectedMessage, handler.GetRawRequest());
92 }
93
TEST(WebSocketHandshakeResponseHandlerTest,SimpleResponse)94 TEST(WebSocketHandshakeResponseHandlerTest, SimpleResponse) {
95 WebSocketHandshakeResponseHandler handler;
96
97 static const char kHandshakeResponseMessage[] =
98 "HTTP/1.1 101 Switching Protocols\r\n"
99 "Upgrade: websocket\r\n"
100 "Connection: Upgrade\r\n"
101 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
102 "Sec-WebSocket-Protocol: sample\r\n"
103 "\r\n";
104
105 EXPECT_EQ(strlen(kHandshakeResponseMessage),
106 handler.ParseRawResponse(kHandshakeResponseMessage,
107 strlen(kHandshakeResponseMessage)));
108 EXPECT_TRUE(handler.HasResponse());
109
110 handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
111
112 EXPECT_EQ(kHandshakeResponseMessage, handler.GetResponse());
113 }
114
TEST(WebSocketHandshakeResponseHandlerTest,ReplaceResponseCookies)115 TEST(WebSocketHandshakeResponseHandlerTest, ReplaceResponseCookies) {
116 WebSocketHandshakeResponseHandler handler;
117
118 static const char kHandshakeResponseMessage[] =
119 "HTTP/1.1 101 Switching Protocols\r\n"
120 "Upgrade: websocket\r\n"
121 "Connection: Upgrade\r\n"
122 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
123 "Sec-WebSocket-Protocol: sample\r\n"
124 "Set-Cookie: WK-websocket-test-1\r\n"
125 "Set-Cookie: WK-websocket-test-httponly=1; HttpOnly\r\n"
126 "\r\n";
127
128 EXPECT_EQ(strlen(kHandshakeResponseMessage),
129 handler.ParseRawResponse(kHandshakeResponseMessage,
130 strlen(kHandshakeResponseMessage)));
131 EXPECT_TRUE(handler.HasResponse());
132 std::vector<std::string> cookies;
133 handler.GetHeaders(kSetCookieHeaders, arraysize(kSetCookieHeaders), &cookies);
134 ASSERT_EQ(2U, cookies.size());
135 EXPECT_EQ("WK-websocket-test-1", cookies[0]);
136 EXPECT_EQ("WK-websocket-test-httponly=1; HttpOnly", cookies[1]);
137 handler.RemoveHeaders(kSetCookieHeaders, arraysize(kSetCookieHeaders));
138
139 static const char kHandshakeResponseExpectedMessage[] =
140 "HTTP/1.1 101 Switching Protocols\r\n"
141 "Upgrade: websocket\r\n"
142 "Connection: Upgrade\r\n"
143 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
144 "Sec-WebSocket-Protocol: sample\r\n"
145 "\r\n";
146
147 EXPECT_EQ(kHandshakeResponseExpectedMessage, handler.GetResponse());
148 }
149
TEST(WebSocketHandshakeResponseHandlerTest,BadResponse)150 TEST(WebSocketHandshakeResponseHandlerTest, BadResponse) {
151 WebSocketHandshakeResponseHandler handler;
152
153 static const char kBadMessage[] = "\n\n\r\net-Location: w";
154 EXPECT_EQ(2U, handler.ParseRawResponse(kBadMessage, strlen(kBadMessage)));
155 EXPECT_TRUE(handler.HasResponse());
156 EXPECT_EQ("\n\n", handler.GetResponse());
157 }
158
TEST(WebSocketHandshakeResponseHandlerTest,BadResponse2)159 TEST(WebSocketHandshakeResponseHandlerTest, BadResponse2) {
160 WebSocketHandshakeResponseHandler handler;
161
162 static const char kBadMessage[] = "\n\r\n\r\net-Location: w";
163 EXPECT_EQ(3U, handler.ParseRawResponse(kBadMessage, strlen(kBadMessage)));
164 EXPECT_TRUE(handler.HasResponse());
165 EXPECT_EQ("\n\r\n", handler.GetResponse());
166 }
167
TEST(WebSocketHandshakeHandlerTest,HttpRequestResponse)168 TEST(WebSocketHandshakeHandlerTest, HttpRequestResponse) {
169 WebSocketHandshakeRequestHandler request_handler;
170
171 static const char kHandshakeRequestMessage[] =
172 "GET /demo HTTP/1.1\r\n"
173 "Host: example.com\r\n"
174 "Upgrade: websocket\r\n"
175 "Connection: Upgrade\r\n"
176 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
177 "Sec-WebSocket-Origin: http://example.com\r\n"
178 "Sec-WebSocket-Protocol: sample\r\n"
179 "Sec-WebSocket-Version: 13\r\n"
180 "\r\n";
181
182 EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
183 strlen(kHandshakeRequestMessage)));
184
185 GURL url("ws://example.com/demo");
186 std::string challenge;
187 const HttpRequestInfo& request_info =
188 request_handler.GetRequestInfo(url, &challenge);
189
190 EXPECT_EQ(url, request_info.url);
191 EXPECT_EQ("GET", request_info.method);
192 EXPECT_FALSE(request_info.extra_headers.HasHeader("Upgrade"));
193 EXPECT_FALSE(request_info.extra_headers.HasHeader("Connection"));
194 EXPECT_FALSE(request_info.extra_headers.HasHeader("Sec-WebSocket-Key"));
195 std::string value;
196 EXPECT_TRUE(request_info.extra_headers.GetHeader("Host", &value));
197 EXPECT_EQ("example.com", value);
198 EXPECT_TRUE(request_info.extra_headers.GetHeader("Sec-WebSocket-Origin",
199 &value));
200 EXPECT_EQ("http://example.com", value);
201 EXPECT_TRUE(request_info.extra_headers.GetHeader("Sec-WebSocket-Protocol",
202 &value));
203 EXPECT_EQ("sample", value);
204
205 EXPECT_EQ("dGhlIHNhbXBsZSBub25jZQ==", challenge);
206
207 static const char kHandshakeResponseHeader[] =
208 "HTTP/1.1 101 Switching Protocols\r\n"
209 "Sec-WebSocket-Protocol: sample\r\n";
210
211 std::string raw_headers =
212 HttpUtil::AssembleRawHeaders(kHandshakeResponseHeader,
213 strlen(kHandshakeResponseHeader));
214 HttpResponseInfo response_info;
215 response_info.headers = new HttpResponseHeaders(raw_headers);
216
217 EXPECT_TRUE(StartsWithASCII(response_info.headers->GetStatusLine(),
218 "HTTP/1.1 101 ", false));
219 EXPECT_FALSE(response_info.headers->HasHeader("Upgrade"));
220 EXPECT_FALSE(response_info.headers->HasHeader("Connection"));
221 EXPECT_FALSE(response_info.headers->HasHeader("Sec-WebSocket-Accept"));
222 EXPECT_TRUE(response_info.headers->HasHeaderValue("Sec-WebSocket-Protocol",
223 "sample"));
224
225 WebSocketHandshakeResponseHandler response_handler;
226
227 EXPECT_TRUE(response_handler.ParseResponseInfo(response_info, challenge));
228 EXPECT_TRUE(response_handler.HasResponse());
229
230 static const char kHandshakeResponseExpectedMessage[] =
231 "HTTP/1.1 101 Switching Protocols\r\n"
232 "Upgrade: websocket\r\n"
233 "Connection: Upgrade\r\n"
234 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
235 "Sec-WebSocket-Protocol: sample\r\n"
236 "\r\n";
237
238 EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
239 }
240
241 } // namespace net
242