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