Home | History | Annotate | Download | only in websockets
      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