Add is_upgrade() free function:

fix #195

This function returns `true` when the passed HTTP Request
indicates a WebSocket Upgrade. It does not validate the
contents of the fields: it just trivially accepts requests
which can only be a WebSocket Upgrade message.

Callers who wish to manually read HTTP requests in their
server implementation can use this function to determine if
the request should be routed to an instance of websocket::stream.
This commit is contained in:
Vinnie Falco
2017-04-26 18:20:59 -07:00
parent fa1f4c7d56
commit 4b3a21efec
5 changed files with 105 additions and 1 deletions

View File

@@ -2,6 +2,10 @@
* CMake hide command lines in .vcxproj Output windows"
WebSocket:
* Add is_upgrade() free function
API Changes:
* Provide websocket::stream accept() overloads

View File

@@ -107,6 +107,7 @@
<bridgehead renderas="sect3">Functions</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.websocket__async_teardown">async_teardown</link></member>
<member><link linkend="beast.ref.websocket__is_upgrade">is_upgrade</link></member>
<member><link linkend="beast.ref.websocket__teardown">teardown</link></member>
</simplelist>
<bridgehead renderas="sect3">Options</bridgehead>

View File

@@ -0,0 +1,36 @@
//
// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_WEBSOCKET_IMPL_RFC6455_IPP
#define BEAST_WEBSOCKET_IMPL_RFC6455_IPP
#include <beast/http/rfc7230.hpp>
namespace beast {
namespace websocket {
template<class Fields>
bool
is_upgrade(http::header<true, Fields> const& req)
{
if(req.version < 11)
return false;
if(req.method != "GET")
return false;
if(! http::is_upgrade(req))
return false;
if(! http::token_list{req.fields["Upgrade"]}.exists("websocket"))
return false;
if(! req.fields.exists("Sec-WebSocket-Version"))
return false;
return true;
}
} // websocket
} // beast
#endif

View File

@@ -10,13 +10,34 @@
#include <beast/config.hpp>
#include <beast/core/static_string.hpp>
#include <boost/optional.hpp>
#include <beast/http/message.hpp>
#include <array>
#include <cstdint>
namespace beast {
namespace websocket {
/** Returns `true` if the specified HTTP request is a WebSocket Upgrade.
This function returns `true` when the passed HTTP Request
indicates a WebSocket Upgrade. It does not validate the
contents of the fields: it just trivially accepts requests
which could only possibly be a valid or invalid WebSocket
Upgrade message.
Callers who wish to manually read HTTP requests in their
server implementation can use this function to determine if
the request should be routed to an instance of
@ref websocket::stream.
@param req The HTTP Request object to check.
@return `true` if the request is a WebSocket Upgrade.
*/
template<class Fields>
bool
is_upgrade(beast::http::header<true, Fields> const& req);
/** WebSocket frame header opcodes. */
enum class opcode : std::uint8_t
{
@@ -186,4 +207,6 @@ struct close_reason
} // websocket
} // beast
#include <beast/websocket/impl/rfc6455.ipp>
#endif

View File

@@ -7,3 +7,43 @@
// Test that header file is self-contained.
#include <beast/websocket/rfc6455.hpp>
#include <beast/unit_test/suite.hpp>
namespace beast {
namespace websocket {
class rfc6455_test
: public beast::unit_test::suite
{
public:
void
test_is_upgrade()
{
http::request_header req;
req.version = 10;
BEAST_EXPECT(! is_upgrade(req));
req.version = 11;
req.method = "POST";
req.url = "/";
BEAST_EXPECT(! is_upgrade(req));
req.method = "GET";
req.fields.insert("Connection", "upgrade");
BEAST_EXPECT(! is_upgrade(req));
req.fields.insert("Upgrade", "websocket");
BEAST_EXPECT(! is_upgrade(req));
req.fields.insert("Sec-WebSocket-Version", "13");
BEAST_EXPECT(is_upgrade(req));
}
void
run() override
{
test_is_upgrade();
}
};
BEAST_DEFINE_TESTSUITE(rfc6455,websocket,beast);
} // websocket
} // beast