158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/websockets/websocket_handshake_handler.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_util.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kCookieHeaders[] = {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "cookie", "cookie2"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kSetCookieHeaders[] = {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "set-cookie", "set-cookie2"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketHandshakeRequestHandlerTest, SimpleRequest) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketHandshakeRequestHandler handler;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHandshakeRequestMessage[] =
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "GET /demo HTTP/1.1\r\n"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Host: example.com\r\n"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Upgrade: websocket\r\n"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Connection: Upgrade\r\n"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Origin: http://example.com\r\n"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Protocol: sample\r\n"
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      "Sec-WebSocket-Version: 13\r\n"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\r\n";
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(handler.ParseRequest(kHandshakeRequestMessage,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   strlen(kHandshakeRequestMessage)));
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeRequestMessage, handler.GetRawRequest());
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketHandshakeRequestHandlerTest, ReplaceRequestCookies) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketHandshakeRequestHandler handler;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHandshakeRequestMessage[] =
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "GET /demo HTTP/1.1\r\n"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Host: example.com\r\n"
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Upgrade: websocket\r\n"
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Connection: Upgrade\r\n"
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Origin: http://example.com\r\n"
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Protocol: sample\r\n"
664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      "Sec-WebSocket-Version: 13\r\n"
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Cookie: WK-websocket-test=1\r\n"
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\r\n";
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(handler.ParseRequest(kHandshakeRequestMessage,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   strlen(kHandshakeRequestMessage)));
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler.AppendHeaderIfMissing("Cookie",
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                "WK-websocket-test=1; "
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                "WK-websocket-test-httponly=1");
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHandshakeRequestExpectedMessage[] =
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "GET /demo HTTP/1.1\r\n"
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Host: example.com\r\n"
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Upgrade: websocket\r\n"
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Connection: Upgrade\r\n"
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Origin: http://example.com\r\n"
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Protocol: sample\r\n"
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      "Sec-WebSocket-Version: 13\r\n"
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Cookie: WK-websocket-test=1; WK-websocket-test-httponly=1\r\n"
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\r\n";
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeRequestExpectedMessage, handler.GetRawRequest());
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketHandshakeResponseHandlerTest, SimpleResponse) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketHandshakeResponseHandler handler;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHandshakeResponseMessage[] =
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.1 101 Switching Protocols\r\n"
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Upgrade: websocket\r\n"
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Connection: Upgrade\r\n"
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Protocol: sample\r\n"
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\r\n";
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(strlen(kHandshakeResponseMessage),
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            handler.ParseRawResponse(kHandshakeResponseMessage,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     strlen(kHandshakeResponseMessage)));
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(handler.HasResponse());
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeResponseMessage, handler.GetResponse());
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketHandshakeResponseHandlerTest, ReplaceResponseCookies) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketHandshakeResponseHandler handler;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHandshakeResponseMessage[] =
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.1 101 Switching Protocols\r\n"
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Upgrade: websocket\r\n"
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Connection: Upgrade\r\n"
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Protocol: sample\r\n"
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Set-Cookie: WK-websocket-test-1\r\n"
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Set-Cookie: WK-websocket-test-httponly=1; HttpOnly\r\n"
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\r\n";
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(strlen(kHandshakeResponseMessage),
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            handler.ParseRawResponse(kHandshakeResponseMessage,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     strlen(kHandshakeResponseMessage)));
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(handler.HasResponse());
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> cookies;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler.GetHeaders(kSetCookieHeaders, arraysize(kSetCookieHeaders), &cookies);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2U, cookies.size());
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("WK-websocket-test-1", cookies[0]);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("WK-websocket-test-httponly=1; HttpOnly", cookies[1]);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler.RemoveHeaders(kSetCookieHeaders, arraysize(kSetCookieHeaders));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHandshakeResponseExpectedMessage[] =
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.1 101 Switching Protocols\r\n"
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Upgrade: websocket\r\n"
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Connection: Upgrade\r\n"
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Protocol: sample\r\n"
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\r\n";
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeResponseExpectedMessage, handler.GetResponse());
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketHandshakeResponseHandlerTest, BadResponse) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketHandshakeResponseHandler handler;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kBadMessage[] = "\n\n\r\net-Location: w";
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(2U, handler.ParseRawResponse(kBadMessage, strlen(kBadMessage)));
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(handler.HasResponse());
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ("\n\n", handler.GetResponse());
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketHandshakeResponseHandlerTest, BadResponse2) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketHandshakeResponseHandler handler;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kBadMessage[] = "\n\r\n\r\net-Location: w";
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(3U, handler.ParseRawResponse(kBadMessage, strlen(kBadMessage)));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(handler.HasResponse());
1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ("\n\r\n", handler.GetResponse());
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketHandshakeHandlerTest, HttpRequestResponse) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketHandshakeRequestHandler request_handler;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHandshakeRequestMessage[] =
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "GET /demo HTTP/1.1\r\n"
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Host: example.com\r\n"
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Upgrade: websocket\r\n"
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Connection: Upgrade\r\n"
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Origin: http://example.com\r\n"
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Protocol: sample\r\n"
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      "Sec-WebSocket-Version: 13\r\n"
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\r\n";
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           strlen(kHandshakeRequestMessage)));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url("ws://example.com/demo");
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string challenge;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpRequestInfo& request_info =
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_handler.GetRequestInfo(url, &challenge);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(url, request_info.url);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("GET", request_info.method);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(request_info.extra_headers.HasHeader("Upgrade"));
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(request_info.extra_headers.HasHeader("Connection"));
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(request_info.extra_headers.HasHeader("Sec-WebSocket-Key"));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string value;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(request_info.extra_headers.GetHeader("Host", &value));
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("example.com", value);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(request_info.extra_headers.GetHeader("Sec-WebSocket-Origin",
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   &value));
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("http://example.com", value);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(request_info.extra_headers.GetHeader("Sec-WebSocket-Protocol",
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   &value));
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("sample", value);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("dGhlIHNhbXBsZSBub25jZQ==", challenge);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHandshakeResponseHeader[] =
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.1 101 Switching Protocols\r\n"
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Protocol: sample\r\n";
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string raw_headers =
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HttpUtil::AssembleRawHeaders(kHandshakeResponseHeader,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   strlen(kHandshakeResponseHeader));
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpResponseInfo response_info;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_info.headers = new HttpResponseHeaders(raw_headers);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(StartsWithASCII(response_info.headers->GetStatusLine(),
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              "HTTP/1.1 101 ", false));
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(response_info.headers->HasHeader("Upgrade"));
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(response_info.headers->HasHeader("Connection"));
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(response_info.headers->HasHeader("Sec-WebSocket-Accept"));
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response_info.headers->HasHeaderValue("Sec-WebSocket-Protocol",
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    "sample"));
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketHandshakeResponseHandler response_handler;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response_handler.ParseResponseInfo(response_info, challenge));
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response_handler.HasResponse());
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHandshakeResponseExpectedMessage[] =
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "HTTP/1.1 101 Switching Protocols\r\n"
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Upgrade: websocket\r\n"
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Connection: Upgrade\r\n"
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Protocol: sample\r\n"
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\r\n";
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
242