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. 4 5#include "net/websockets/websocket_handshake_handler.h" 6 7#include <string> 8 9#include "net/socket/next_proto.h" 10#include "net/spdy/spdy_header_block.h" 11#include "net/spdy/spdy_websocket_test_util.h" 12#include "testing/gtest/include/gtest/gtest.h" 13#include "url/gurl.h" 14 15namespace net { 16 17namespace { 18 19class WebSocketHandshakeHandlerSpdyTest 20 : public ::testing::Test, 21 public ::testing::WithParamInterface<NextProto> { 22 protected: 23 WebSocketHandshakeHandlerSpdyTest() : spdy_util_(GetParam()) {} 24 25 SpdyWebSocketTestUtil spdy_util_; 26}; 27 28INSTANTIATE_TEST_CASE_P( 29 NextProto, 30 WebSocketHandshakeHandlerSpdyTest, 31 testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2, 32 kProtoHTTP2Draft04)); 33 34TEST_P(WebSocketHandshakeHandlerSpdyTest, RequestResponse) { 35 WebSocketHandshakeRequestHandler request_handler; 36 37 static const char kHandshakeRequestMessage[] = 38 "GET /demo HTTP/1.1\r\n" 39 "Host: example.com\r\n" 40 "Upgrade: websocket\r\n" 41 "Connection: Upgrade\r\n" 42 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" 43 "Origin: http://example.com\r\n" 44 "Sec-WebSocket-Protocol: sample\r\n" 45 "Sec-WebSocket-Extensions: foo\r\n" 46 "Sec-WebSocket-Version: 13\r\n" 47 "\r\n"; 48 49 EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage, 50 strlen(kHandshakeRequestMessage))); 51 EXPECT_EQ(13, request_handler.protocol_version()); 52 53 GURL url("ws://example.com/demo"); 54 std::string challenge; 55 SpdyHeaderBlock headers; 56 ASSERT_TRUE(request_handler.GetRequestHeaderBlock(url, 57 &headers, 58 &challenge, 59 spdy_util_.spdy_version())); 60 61 EXPECT_EQ(url.path(), spdy_util_.GetHeader(headers, "path")); 62 EXPECT_TRUE(spdy_util_.GetHeader(headers, "upgrade").empty()); 63 EXPECT_TRUE(spdy_util_.GetHeader(headers, "Upgrade").empty()); 64 EXPECT_TRUE(spdy_util_.GetHeader(headers, "connection").empty()); 65 EXPECT_TRUE(spdy_util_.GetHeader(headers, "Connection").empty()); 66 EXPECT_TRUE(spdy_util_.GetHeader(headers, "Sec-WebSocket-Key").empty()); 67 EXPECT_TRUE(spdy_util_.GetHeader(headers, "sec-websocket-key").empty()); 68 EXPECT_TRUE(spdy_util_.GetHeader(headers, "Sec-WebSocket-Version").empty()); 69 EXPECT_TRUE(spdy_util_.GetHeader(headers, "sec-webSocket-version").empty()); 70 EXPECT_EQ("example.com", spdy_util_.GetHeader(headers, "host")); 71 EXPECT_EQ("http://example.com", spdy_util_.GetHeader(headers, "origin")); 72 EXPECT_EQ("sample", spdy_util_.GetHeader(headers, "sec-websocket-protocol")); 73 EXPECT_EQ("foo", spdy_util_.GetHeader(headers, "sec-websocket-extensions")); 74 EXPECT_EQ("ws", spdy_util_.GetHeader(headers, "scheme")); 75 EXPECT_EQ("WebSocket/13", spdy_util_.GetHeader(headers, "version")); 76 77 static const char expected_challenge[] = "dGhlIHNhbXBsZSBub25jZQ=="; 78 79 EXPECT_EQ(expected_challenge, challenge); 80 81 headers.clear(); 82 83 spdy_util_.SetHeader("status", "101 Switching Protocols", &headers); 84 spdy_util_.SetHeader("sec-websocket-protocol", "sample", &headers); 85 spdy_util_.SetHeader("sec-websocket-extensions", "foo", &headers); 86 87 WebSocketHandshakeResponseHandler response_handler; 88 response_handler.set_protocol_version(13); 89 EXPECT_TRUE(response_handler.ParseResponseHeaderBlock( 90 headers, challenge, spdy_util_.spdy_version())); 91 EXPECT_TRUE(response_handler.HasResponse()); 92 93 // Note that order of sec-websocket-* is sensitive with hash_map order. 94 static const char kHandshakeResponseExpectedMessage[] = 95 "HTTP/1.1 101 Switching Protocols\r\n" 96 "Upgrade: websocket\r\n" 97 "Connection: Upgrade\r\n" 98 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 99 "sec-websocket-extensions: foo\r\n" 100 "sec-websocket-protocol: sample\r\n" 101 "\r\n"; 102 103 EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse()); 104} 105 106TEST_P(WebSocketHandshakeHandlerSpdyTest, RequestResponseWithCookies) { 107 WebSocketHandshakeRequestHandler request_handler; 108 109 // Note that websocket won't use multiple headers in request now. 110 static const char kHandshakeRequestMessage[] = 111 "GET /demo HTTP/1.1\r\n" 112 "Host: example.com\r\n" 113 "Upgrade: websocket\r\n" 114 "Connection: Upgrade\r\n" 115 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" 116 "Origin: http://example.com\r\n" 117 "Sec-WebSocket-Protocol: sample\r\n" 118 "Sec-WebSocket-Extensions: foo\r\n" 119 "Sec-WebSocket-Version: 13\r\n" 120 "Cookie: WK-websocket-test=1; WK-websocket-test-httponly=1\r\n" 121 "\r\n"; 122 123 EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage, 124 strlen(kHandshakeRequestMessage))); 125 EXPECT_EQ(13, request_handler.protocol_version()); 126 127 GURL url("ws://example.com/demo"); 128 std::string challenge; 129 SpdyHeaderBlock headers; 130 ASSERT_TRUE(request_handler.GetRequestHeaderBlock(url, 131 &headers, 132 &challenge, 133 spdy_util_.spdy_version())); 134 135 EXPECT_EQ(url.path(), spdy_util_.GetHeader(headers, "path")); 136 EXPECT_TRUE(spdy_util_.GetHeader(headers, "upgrade").empty()); 137 EXPECT_TRUE(spdy_util_.GetHeader(headers, "Upgrade").empty()); 138 EXPECT_TRUE(spdy_util_.GetHeader(headers, "connection").empty()); 139 EXPECT_TRUE(spdy_util_.GetHeader(headers, "Connection").empty()); 140 EXPECT_TRUE(spdy_util_.GetHeader(headers, "Sec-WebSocket-Key").empty()); 141 EXPECT_TRUE(spdy_util_.GetHeader(headers, "sec-websocket-key").empty()); 142 EXPECT_TRUE(spdy_util_.GetHeader(headers, "Sec-WebSocket-Version").empty()); 143 EXPECT_TRUE(spdy_util_.GetHeader(headers, "sec-webSocket-version").empty()); 144 EXPECT_EQ("example.com", spdy_util_.GetHeader(headers, "host")); 145 EXPECT_EQ("http://example.com", spdy_util_.GetHeader(headers, "origin")); 146 EXPECT_EQ("sample", spdy_util_.GetHeader(headers, "sec-websocket-protocol")); 147 EXPECT_EQ("foo", spdy_util_.GetHeader(headers, "sec-websocket-extensions")); 148 EXPECT_EQ("ws", spdy_util_.GetHeader(headers, "scheme")); 149 EXPECT_EQ("WebSocket/13", spdy_util_.GetHeader(headers, "version")); 150 EXPECT_EQ("WK-websocket-test=1; WK-websocket-test-httponly=1", 151 headers["cookie"]); 152 153 const char expected_challenge[] = "dGhlIHNhbXBsZSBub25jZQ=="; 154 155 EXPECT_EQ(expected_challenge, challenge); 156 157 headers.clear(); 158 159 spdy_util_.SetHeader("status", "101 Switching Protocols", &headers); 160 spdy_util_.SetHeader("sec-websocket-protocol", "sample", &headers); 161 spdy_util_.SetHeader("sec-websocket-extensions", "foo", &headers); 162 std::string cookie = "WK-websocket-test=1"; 163 cookie.append(1, '\0'); 164 cookie += "WK-websocket-test-httponly=1; HttpOnly"; 165 headers["set-cookie"] = cookie; 166 167 168 WebSocketHandshakeResponseHandler response_handler; 169 response_handler.set_protocol_version(13); 170 EXPECT_TRUE(response_handler.ParseResponseHeaderBlock( 171 headers, challenge, spdy_util_.spdy_version())); 172 EXPECT_TRUE(response_handler.HasResponse()); 173 174 // Note that order of sec-websocket-* is sensitive with hash_map order. 175 static const char kHandshakeResponseExpectedMessage[] = 176 "HTTP/1.1 101 Switching Protocols\r\n" 177 "Upgrade: websocket\r\n" 178 "Connection: Upgrade\r\n" 179 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 180 "sec-websocket-extensions: foo\r\n" 181 "sec-websocket-protocol: sample\r\n" 182 "set-cookie: WK-websocket-test=1\r\n" 183 "set-cookie: WK-websocket-test-httponly=1; HttpOnly\r\n" 184 "\r\n"; 185 186 EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse()); 187} 188 189} // namespace 190 191} // namespace net 192