1 // Copyright (c) 2012 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.
5 #include "net/websockets/websocket_handshake_handler.h"
10 #include "base/basictypes.h"
11 #include "base/string_util.h"
12 #include "googleurl/src/gurl.h"
13 #include "net/http/http_response_headers.h"
14 #include "net/http/http_util.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "testing/platform_test.h"
22 const char* const kCookieHeaders
[] = {
26 const char* const kSetCookieHeaders
[] = {
27 "set-cookie", "set-cookie2"
34 TEST(WebSocketHandshakeRequestHandlerTest
, SimpleRequest
) {
35 WebSocketHandshakeRequestHandler handler
;
37 static const char kHandshakeRequestMessage
[] =
38 "GET /demo HTTP/1.1\r\n"
39 "Host: example.com\r\n"
40 "Connection: Upgrade\r\n"
41 "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"
42 "Sec-WebSocket-Protocol: sample\r\n"
43 "Upgrade: WebSocket\r\n"
44 "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
45 "Origin: http://example.com\r\n"
49 EXPECT_TRUE(handler
.ParseRequest(kHandshakeRequestMessage
,
50 strlen(kHandshakeRequestMessage
)));
51 EXPECT_EQ(0, handler
.protocol_version());
53 handler
.RemoveHeaders(kCookieHeaders
, arraysize(kCookieHeaders
));
55 EXPECT_EQ(kHandshakeRequestMessage
, handler
.GetRawRequest());
58 TEST(WebSocketHandshakeRequestHandlerTest
, SimpleRequestHybi06Handshake
) {
59 WebSocketHandshakeRequestHandler handler
;
61 static const char kHandshakeRequestMessage
[] =
62 "GET /demo HTTP/1.1\r\n"
63 "Host: example.com\r\n"
64 "Upgrade: websocket\r\n"
65 "Connection: Upgrade\r\n"
66 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
67 "Sec-WebSocket-Origin: http://example.com\r\n"
68 "Sec-WebSocket-Protocol: sample\r\n"
69 "Sec-WebSocket-Version: 6\r\n"
72 EXPECT_TRUE(handler
.ParseRequest(kHandshakeRequestMessage
,
73 strlen(kHandshakeRequestMessage
)));
74 EXPECT_EQ(6, handler
.protocol_version());
76 handler
.RemoveHeaders(kCookieHeaders
, arraysize(kCookieHeaders
));
78 EXPECT_EQ(kHandshakeRequestMessage
, handler
.GetRawRequest());
81 TEST(WebSocketHandshakeRequestHandlerTest
, ReplaceRequestCookies
) {
82 WebSocketHandshakeRequestHandler handler
;
84 static const char kHandshakeRequestMessage
[] =
85 "GET /demo HTTP/1.1\r\n"
86 "Host: example.com\r\n"
87 "Connection: Upgrade\r\n"
88 "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"
89 "Sec-WebSocket-Protocol: sample\r\n"
90 "Upgrade: WebSocket\r\n"
91 "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
92 "Origin: http://example.com\r\n"
93 "Cookie: WK-websocket-test=1\r\n"
97 EXPECT_TRUE(handler
.ParseRequest(kHandshakeRequestMessage
,
98 strlen(kHandshakeRequestMessage
)));
99 EXPECT_EQ(0, handler
.protocol_version());
101 handler
.RemoveHeaders(kCookieHeaders
, arraysize(kCookieHeaders
));
103 handler
.AppendHeaderIfMissing("Cookie",
104 "WK-websocket-test=1; "
105 "WK-websocket-test-httponly=1");
107 static const char kHandshakeRequestExpectedMessage
[] =
108 "GET /demo HTTP/1.1\r\n"
109 "Host: example.com\r\n"
110 "Connection: Upgrade\r\n"
111 "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"
112 "Sec-WebSocket-Protocol: sample\r\n"
113 "Upgrade: WebSocket\r\n"
114 "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
115 "Origin: http://example.com\r\n"
116 "Cookie: WK-websocket-test=1; WK-websocket-test-httponly=1\r\n"
120 EXPECT_EQ(kHandshakeRequestExpectedMessage
, handler
.GetRawRequest());
123 TEST(WebSocketHandshakeRequestHandlerTest
,
124 ReplaceRequestCookiesHybi06Handshake
) {
125 WebSocketHandshakeRequestHandler handler
;
127 static const char kHandshakeRequestMessage
[] =
128 "GET /demo HTTP/1.1\r\n"
129 "Host: example.com\r\n"
130 "Upgrade: websocket\r\n"
131 "Connection: Upgrade\r\n"
132 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
133 "Sec-WebSocket-Origin: http://example.com\r\n"
134 "Sec-WebSocket-Protocol: sample\r\n"
135 "Sec-WebSocket-Version: 6\r\n"
136 "Cookie: WK-websocket-test=1\r\n"
139 EXPECT_TRUE(handler
.ParseRequest(kHandshakeRequestMessage
,
140 strlen(kHandshakeRequestMessage
)));
141 EXPECT_EQ(6, handler
.protocol_version());
143 handler
.RemoveHeaders(kCookieHeaders
, arraysize(kCookieHeaders
));
145 handler
.AppendHeaderIfMissing("Cookie",
146 "WK-websocket-test=1; "
147 "WK-websocket-test-httponly=1");
149 static const char kHandshakeRequestExpectedMessage
[] =
150 "GET /demo HTTP/1.1\r\n"
151 "Host: example.com\r\n"
152 "Upgrade: websocket\r\n"
153 "Connection: Upgrade\r\n"
154 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
155 "Sec-WebSocket-Origin: http://example.com\r\n"
156 "Sec-WebSocket-Protocol: sample\r\n"
157 "Sec-WebSocket-Version: 6\r\n"
158 "Cookie: WK-websocket-test=1; WK-websocket-test-httponly=1\r\n"
161 EXPECT_EQ(kHandshakeRequestExpectedMessage
, handler
.GetRawRequest());
164 TEST(WebSocketHandshakeResponseHandlerTest
, SimpleResponse
) {
165 WebSocketHandshakeResponseHandler handler
;
166 EXPECT_EQ(0, handler
.protocol_version());
168 static const char kHandshakeResponseMessage
[] =
169 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
170 "Upgrade: WebSocket\r\n"
171 "Connection: Upgrade\r\n"
172 "Sec-WebSocket-Origin: http://example.com\r\n"
173 "Sec-WebSocket-Location: ws://example.com/demo\r\n"
174 "Sec-WebSocket-Protocol: sample\r\n"
178 EXPECT_EQ(strlen(kHandshakeResponseMessage
),
179 handler
.ParseRawResponse(kHandshakeResponseMessage
,
180 strlen(kHandshakeResponseMessage
)));
181 EXPECT_TRUE(handler
.HasResponse());
183 handler
.RemoveHeaders(kCookieHeaders
, arraysize(kCookieHeaders
));
185 EXPECT_EQ(kHandshakeResponseMessage
, handler
.GetResponse());
188 TEST(WebSocketHandshakeResponseHandlerTest
, SimpleResponseHybi06Handshake
) {
189 WebSocketHandshakeResponseHandler handler
;
190 handler
.set_protocol_version(6);
191 EXPECT_EQ(6, handler
.protocol_version());
193 static const char kHandshakeResponseMessage
[] =
194 "HTTP/1.1 101 Switching Protocols\r\n"
195 "Upgrade: websocket\r\n"
196 "Connection: Upgrade\r\n"
197 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
198 "Sec-WebSocket-Protocol: sample\r\n"
201 EXPECT_EQ(strlen(kHandshakeResponseMessage
),
202 handler
.ParseRawResponse(kHandshakeResponseMessage
,
203 strlen(kHandshakeResponseMessage
)));
204 EXPECT_TRUE(handler
.HasResponse());
206 handler
.RemoveHeaders(kCookieHeaders
, arraysize(kCookieHeaders
));
208 EXPECT_EQ(kHandshakeResponseMessage
, handler
.GetResponse());
211 TEST(WebSocketHandshakeResponseHandlerTest
, ReplaceResponseCookies
) {
212 WebSocketHandshakeResponseHandler handler
;
213 EXPECT_EQ(0, handler
.protocol_version());
215 static const char kHandshakeResponseMessage
[] =
216 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
217 "Upgrade: WebSocket\r\n"
218 "Connection: Upgrade\r\n"
219 "Sec-WebSocket-Origin: http://example.com\r\n"
220 "Sec-WebSocket-Location: ws://example.com/demo\r\n"
221 "Sec-WebSocket-Protocol: sample\r\n"
222 "Set-Cookie: WK-websocket-test-1\r\n"
223 "Set-Cookie: WK-websocket-test-httponly=1; HttpOnly\r\n"
227 EXPECT_EQ(strlen(kHandshakeResponseMessage
),
228 handler
.ParseRawResponse(kHandshakeResponseMessage
,
229 strlen(kHandshakeResponseMessage
)));
230 EXPECT_TRUE(handler
.HasResponse());
231 std::vector
<std::string
> cookies
;
232 handler
.GetHeaders(kSetCookieHeaders
, arraysize(kSetCookieHeaders
), &cookies
);
233 ASSERT_EQ(2U, cookies
.size());
234 EXPECT_EQ("WK-websocket-test-1", cookies
[0]);
235 EXPECT_EQ("WK-websocket-test-httponly=1; HttpOnly", cookies
[1]);
236 handler
.RemoveHeaders(kSetCookieHeaders
, arraysize(kSetCookieHeaders
));
238 static const char kHandshakeResponseExpectedMessage
[] =
239 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
240 "Upgrade: WebSocket\r\n"
241 "Connection: Upgrade\r\n"
242 "Sec-WebSocket-Origin: http://example.com\r\n"
243 "Sec-WebSocket-Location: ws://example.com/demo\r\n"
244 "Sec-WebSocket-Protocol: sample\r\n"
248 EXPECT_EQ(kHandshakeResponseExpectedMessage
, handler
.GetResponse());
251 TEST(WebSocketHandshakeResponseHandlerTest
,
252 ReplaceResponseCookiesHybi06Handshake
) {
253 WebSocketHandshakeResponseHandler handler
;
254 handler
.set_protocol_version(6);
255 EXPECT_EQ(6, handler
.protocol_version());
257 static const char kHandshakeResponseMessage
[] =
258 "HTTP/1.1 101 Switching Protocols\r\n"
259 "Upgrade: websocket\r\n"
260 "Connection: Upgrade\r\n"
261 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
262 "Sec-WebSocket-Protocol: sample\r\n"
263 "Set-Cookie: WK-websocket-test-1\r\n"
264 "Set-Cookie: WK-websocket-test-httponly=1; HttpOnly\r\n"
267 EXPECT_EQ(strlen(kHandshakeResponseMessage
),
268 handler
.ParseRawResponse(kHandshakeResponseMessage
,
269 strlen(kHandshakeResponseMessage
)));
270 EXPECT_TRUE(handler
.HasResponse());
271 std::vector
<std::string
> cookies
;
272 handler
.GetHeaders(kSetCookieHeaders
, arraysize(kSetCookieHeaders
), &cookies
);
273 ASSERT_EQ(2U, cookies
.size());
274 EXPECT_EQ("WK-websocket-test-1", cookies
[0]);
275 EXPECT_EQ("WK-websocket-test-httponly=1; HttpOnly", cookies
[1]);
276 handler
.RemoveHeaders(kSetCookieHeaders
, arraysize(kSetCookieHeaders
));
278 static const char kHandshakeResponseExpectedMessage
[] =
279 "HTTP/1.1 101 Switching Protocols\r\n"
280 "Upgrade: websocket\r\n"
281 "Connection: Upgrade\r\n"
282 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
283 "Sec-WebSocket-Protocol: sample\r\n"
286 EXPECT_EQ(kHandshakeResponseExpectedMessage
, handler
.GetResponse());
289 TEST(WebSocketHandshakeResponseHandlerTest
, BadResponse
) {
290 WebSocketHandshakeResponseHandler handler
;
292 static const char kBadMessage
[] = "\n\n\r\net-Location: w";
293 EXPECT_EQ(strlen(kBadMessage
),
294 handler
.ParseRawResponse(kBadMessage
, strlen(kBadMessage
)));
295 EXPECT_TRUE(handler
.HasResponse());
296 EXPECT_EQ(kBadMessage
, handler
.GetResponse());
299 TEST(WebSocketHandshakeResponseHandlerTest
, BadResponse2
) {
300 WebSocketHandshakeResponseHandler handler
;
302 static const char kBadMessage
[] = "\n\r\n\r\net-Location: w";
303 EXPECT_EQ(strlen(kBadMessage
),
304 handler
.ParseRawResponse(kBadMessage
, strlen(kBadMessage
)));
305 EXPECT_TRUE(handler
.HasResponse());
306 EXPECT_EQ(kBadMessage
, handler
.GetResponse());
309 TEST(WebSocketHandshakeHandlerTest
, HttpRequestResponse
) {
310 WebSocketHandshakeRequestHandler request_handler
;
312 static const char kHandshakeRequestMessage
[] =
313 "GET /demo HTTP/1.1\r\n"
314 "Host: example.com\r\n"
315 "Connection: Upgrade\r\n"
316 "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"
317 "Sec-WebSocket-Protocol: sample\r\n"
318 "Upgrade: WebSocket\r\n"
319 "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
320 "Origin: http://example.com\r\n"
324 EXPECT_TRUE(request_handler
.ParseRequest(kHandshakeRequestMessage
,
325 strlen(kHandshakeRequestMessage
)));
326 EXPECT_EQ(0, request_handler
.protocol_version());
328 GURL
url("ws://example.com/demo");
329 std::string challenge
;
330 const HttpRequestInfo
& request_info
=
331 request_handler
.GetRequestInfo(url
, &challenge
);
333 EXPECT_EQ(url
, request_info
.url
);
334 EXPECT_EQ("GET", request_info
.method
);
335 EXPECT_FALSE(request_info
.extra_headers
.HasHeader("Upgrade"));
336 EXPECT_FALSE(request_info
.extra_headers
.HasHeader("Connection"));
337 EXPECT_FALSE(request_info
.extra_headers
.HasHeader("Sec-WebSocket-Key1"));
338 EXPECT_FALSE(request_info
.extra_headers
.HasHeader("Sec-WebSocket-Key2"));
340 EXPECT_TRUE(request_info
.extra_headers
.GetHeader("Host", &value
));
341 EXPECT_EQ("example.com", value
);
342 EXPECT_TRUE(request_info
.extra_headers
.GetHeader("Origin", &value
));
343 EXPECT_EQ("http://example.com", value
);
344 EXPECT_TRUE(request_info
.extra_headers
.GetHeader("Sec-WebSocket-Protocol",
346 EXPECT_EQ("sample", value
);
348 const char expected_challenge
[] = "\x31\x6e\x41\x13\x0f\x7e\xd6\x3c^n:ds[4U";
350 EXPECT_EQ(expected_challenge
, challenge
);
352 static const char kHandshakeResponseHeader
[] =
353 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
354 "Sec-WebSocket-Origin: http://example.com\r\n"
355 "Sec-WebSocket-Location: ws://example.com/demo\r\n"
356 "Sec-WebSocket-Protocol: sample\r\n";
358 std::string raw_headers
=
359 HttpUtil::AssembleRawHeaders(kHandshakeResponseHeader
,
360 strlen(kHandshakeResponseHeader
));
361 HttpResponseInfo response_info
;
362 response_info
.headers
= new HttpResponseHeaders(raw_headers
);
364 EXPECT_TRUE(StartsWithASCII(response_info
.headers
->GetStatusLine(),
365 "HTTP/1.1 101 ", false));
366 EXPECT_FALSE(response_info
.headers
->HasHeader("Upgrade"));
367 EXPECT_FALSE(response_info
.headers
->HasHeader("Connection"));
368 EXPECT_TRUE(response_info
.headers
->HasHeaderValue("Sec-WebSocket-Origin",
369 "http://example.com"));
370 EXPECT_TRUE(response_info
.headers
->HasHeaderValue("Sec-WebSocket-Location",
371 "ws://example.com/demo"));
372 EXPECT_TRUE(response_info
.headers
->HasHeaderValue("Sec-WebSocket-Protocol",
375 WebSocketHandshakeResponseHandler response_handler
;
376 EXPECT_EQ(0, response_handler
.protocol_version());
377 EXPECT_TRUE(response_handler
.ParseResponseInfo(response_info
, challenge
));
378 EXPECT_TRUE(response_handler
.HasResponse());
380 static const char kHandshakeResponseExpectedMessage
[] =
381 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
382 "Upgrade: WebSocket\r\n"
383 "Connection: Upgrade\r\n"
384 "Sec-WebSocket-Origin: http://example.com\r\n"
385 "Sec-WebSocket-Location: ws://example.com/demo\r\n"
386 "Sec-WebSocket-Protocol: sample\r\n"
390 EXPECT_EQ(kHandshakeResponseExpectedMessage
, response_handler
.GetResponse());
393 TEST(WebSocketHandshakeHandlerTest
, HttpRequestResponseHybi06Handshake
) {
394 WebSocketHandshakeRequestHandler request_handler
;
396 static const char kHandshakeRequestMessage
[] =
397 "GET /demo HTTP/1.1\r\n"
398 "Host: example.com\r\n"
399 "Upgrade: websocket\r\n"
400 "Connection: Upgrade\r\n"
401 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
402 "Sec-WebSocket-Origin: http://example.com\r\n"
403 "Sec-WebSocket-Protocol: sample\r\n"
404 "Sec-WebSocket-Version: 6\r\n"
407 EXPECT_TRUE(request_handler
.ParseRequest(kHandshakeRequestMessage
,
408 strlen(kHandshakeRequestMessage
)));
409 EXPECT_EQ(6, request_handler
.protocol_version());
411 GURL
url("ws://example.com/demo");
412 std::string challenge
;
413 const HttpRequestInfo
& request_info
=
414 request_handler
.GetRequestInfo(url
, &challenge
);
416 EXPECT_EQ(url
, request_info
.url
);
417 EXPECT_EQ("GET", request_info
.method
);
418 EXPECT_FALSE(request_info
.extra_headers
.HasHeader("Upgrade"));
419 EXPECT_FALSE(request_info
.extra_headers
.HasHeader("Connection"));
420 EXPECT_FALSE(request_info
.extra_headers
.HasHeader("Sec-WebSocket-Key"));
422 EXPECT_TRUE(request_info
.extra_headers
.GetHeader("Host", &value
));
423 EXPECT_EQ("example.com", value
);
424 EXPECT_TRUE(request_info
.extra_headers
.GetHeader("Sec-WebSocket-Origin",
426 EXPECT_EQ("http://example.com", value
);
427 EXPECT_TRUE(request_info
.extra_headers
.GetHeader("Sec-WebSocket-Protocol",
429 EXPECT_EQ("sample", value
);
431 EXPECT_EQ("dGhlIHNhbXBsZSBub25jZQ==", challenge
);
433 static const char kHandshakeResponseHeader
[] =
434 "HTTP/1.1 101 Switching Protocols\r\n"
435 "Sec-WebSocket-Protocol: sample\r\n";
437 std::string raw_headers
=
438 HttpUtil::AssembleRawHeaders(kHandshakeResponseHeader
,
439 strlen(kHandshakeResponseHeader
));
440 HttpResponseInfo response_info
;
441 response_info
.headers
= new HttpResponseHeaders(raw_headers
);
443 EXPECT_TRUE(StartsWithASCII(response_info
.headers
->GetStatusLine(),
444 "HTTP/1.1 101 ", false));
445 EXPECT_FALSE(response_info
.headers
->HasHeader("Upgrade"));
446 EXPECT_FALSE(response_info
.headers
->HasHeader("Connection"));
447 EXPECT_FALSE(response_info
.headers
->HasHeader("Sec-WebSocket-Accept"));
448 EXPECT_TRUE(response_info
.headers
->HasHeaderValue("Sec-WebSocket-Protocol",
451 WebSocketHandshakeResponseHandler response_handler
;
452 response_handler
.set_protocol_version(request_handler
.protocol_version());
453 EXPECT_EQ(6, response_handler
.protocol_version());
455 EXPECT_TRUE(response_handler
.ParseResponseInfo(response_info
, challenge
));
456 EXPECT_TRUE(response_handler
.HasResponse());
458 static const char kHandshakeResponseExpectedMessage
[] =
459 "HTTP/1.1 101 Switching Protocols\r\n"
460 "Upgrade: websocket\r\n"
461 "Connection: Upgrade\r\n"
462 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
463 "Sec-WebSocket-Protocol: sample\r\n"
466 EXPECT_EQ(kHandshakeResponseExpectedMessage
, response_handler
.GetResponse());