diff --git a/CHANGELOG.md b/CHANGELOG.md index 40698038..72e922bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/doc/quickref.xml b/doc/quickref.xml index a1afe585..f623a339 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -107,6 +107,7 @@ Functions async_teardown + is_upgrade teardown Options diff --git a/include/beast/websocket/impl/rfc6455.ipp b/include/beast/websocket/impl/rfc6455.ipp new file mode 100644 index 00000000..684112bb --- /dev/null +++ b/include/beast/websocket/impl/rfc6455.ipp @@ -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 + +namespace beast { +namespace websocket { + +template +bool +is_upgrade(http::header 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 diff --git a/include/beast/websocket/rfc6455.hpp b/include/beast/websocket/rfc6455.hpp index 6051ebff..6813ed3f 100644 --- a/include/beast/websocket/rfc6455.hpp +++ b/include/beast/websocket/rfc6455.hpp @@ -10,13 +10,34 @@ #include #include -#include +#include #include #include 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 +bool +is_upgrade(beast::http::header const& req); + /** WebSocket frame header opcodes. */ enum class opcode : std::uint8_t { @@ -186,4 +207,6 @@ struct close_reason } // websocket } // beast +#include + #endif diff --git a/test/websocket/rfc6455.cpp b/test/websocket/rfc6455.cpp index c34daf31..080b5f43 100644 --- a/test/websocket/rfc6455.cpp +++ b/test/websocket/rfc6455.cpp @@ -7,3 +7,43 @@ // Test that header file is self-contained. #include + +#include + +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