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 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 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 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 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 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 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 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