From c397227eb54b95e440288271f4d7dd30a201affd Mon Sep 17 00:00:00 2001 From: Richard Hodges Date: Wed, 8 Apr 2020 14:09:24 +0200 Subject: [PATCH] Fix Host header in websocket examples closes #1633 --- CHANGELOG.md | 6 ++++++ .../websocket_client_async_ssl_system_executor.cpp | 7 ++++++- .../client/async-ssl/websocket_client_async_ssl.cpp | 7 ++++++- .../client/async/websocket_client_async.cpp | 7 ++++++- .../client/coro-ssl/websocket_client_coro_ssl.cpp | 9 +++++++-- .../websocket/client/coro/websocket_client_coro.cpp | 9 +++++++-- .../client/sync-ssl/websocket_client_sync_ssl.cpp | 13 +++++++++---- .../websocket/client/sync/websocket_client_sync.cpp | 13 +++++++++---- 8 files changed, 56 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 482bb1e5..13d319b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Version XXX: + +* Fix Host header in websocket examples + +-------------------------------------------------------------------------------- + Version 288: * Fix Content-Length parsing diff --git a/example/websocket/client/async-ssl-system-executor/websocket_client_async_ssl_system_executor.cpp b/example/websocket/client/async-ssl-system-executor/websocket_client_async_ssl_system_executor.cpp index 352bc334..40d19fd0 100644 --- a/example/websocket/client/async-ssl-system-executor/websocket_client_async_ssl_system_executor.cpp +++ b/example/websocket/client/async-ssl-system-executor/websocket_client_async_ssl_system_executor.cpp @@ -109,11 +109,16 @@ public: } void - on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type) + on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type ep) { if(ec) return fail(ec, "connect"); + // Update the host_ string. This will provide the value of the + // Host HTTP header during the WebSocket handshake. + // See https://tools.ietf.org/html/rfc7230#section-5.4 + host_ += ':' + std::to_string(ep.port()); + // Set a timeout on the operation beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30)); diff --git a/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp b/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp index 7251620a..4d413aa7 100644 --- a/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp +++ b/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp @@ -101,11 +101,16 @@ public: } void - on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type) + on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type ep) { if(ec) return fail(ec, "connect"); + // Update the host_ string. This will provide the value of the + // Host HTTP header during the WebSocket handshake. + // See https://tools.ietf.org/html/rfc7230#section-5.4 + host_ += ':' + std::to_string(ep.port()); + // Set a timeout on the operation beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30)); diff --git a/example/websocket/client/async/websocket_client_async.cpp b/example/websocket/client/async/websocket_client_async.cpp index 15b127d3..5fcf721b 100644 --- a/example/websocket/client/async/websocket_client_async.cpp +++ b/example/websocket/client/async/websocket_client_async.cpp @@ -95,7 +95,7 @@ public: } void - on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type) + on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type ep) { if(ec) return fail(ec, "connect"); @@ -118,6 +118,11 @@ public: " websocket-client-async"); })); + // Update the host_ string. This will provide the value of the + // Host HTTP header during the WebSocket handshake. + // See https://tools.ietf.org/html/rfc7230#section-5.4 + host_ += ':' + std::to_string(ep.port()); + // Perform the websocket handshake ws_.async_handshake(host_, "/", beast::bind_front_handler( diff --git a/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp b/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp index d4d8ba32..5b4d9e9b 100644 --- a/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp +++ b/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp @@ -44,7 +44,7 @@ fail(beast::error_code ec, char const* what) // Sends a WebSocket message and prints the response void do_session( - std::string const& host, + std::string host, std::string const& port, std::string const& text, net::io_context& ioc, @@ -67,10 +67,15 @@ do_session( beast::get_lowest_layer(ws).expires_after(std::chrono::seconds(30)); // Make the connection on the IP address we get from a lookup - beast::get_lowest_layer(ws).async_connect(results, yield[ec]); + auto ep = beast::get_lowest_layer(ws).async_connect(results, yield[ec]); if(ec) return fail(ec, "connect"); + // Update the host_ string. This will provide the value of the + // Host HTTP header during the WebSocket handshake. + // See https://tools.ietf.org/html/rfc7230#section-5.4 + host += ':' + std::to_string(ep.port()); + // Set a timeout on the operation beast::get_lowest_layer(ws).expires_after(std::chrono::seconds(30)); diff --git a/example/websocket/client/coro/websocket_client_coro.cpp b/example/websocket/client/coro/websocket_client_coro.cpp index 359015b2..7a4b0616 100644 --- a/example/websocket/client/coro/websocket_client_coro.cpp +++ b/example/websocket/client/coro/websocket_client_coro.cpp @@ -39,7 +39,7 @@ fail(beast::error_code ec, char const* what) // Sends a WebSocket message and prints the response void do_session( - std::string const& host, + std::string host, std::string const& port, std::string const& text, net::io_context& ioc, @@ -60,10 +60,15 @@ do_session( beast::get_lowest_layer(ws).expires_after(std::chrono::seconds(30)); // Make the connection on the IP address we get from a lookup - beast::get_lowest_layer(ws).async_connect(results, yield[ec]); + auto ep = beast::get_lowest_layer(ws).async_connect(results, yield[ec]); if(ec) return fail(ec, "connect"); + // Update the host_ string. This will provide the value of the + // Host HTTP header during the WebSocket handshake. + // See https://tools.ietf.org/html/rfc7230#section-5.4 + host += ':' + std::to_string(ep.port()); + // Turn off the timeout on the tcp_stream, because // the websocket stream has its own timeout system. beast::get_lowest_layer(ws).expires_never(); diff --git a/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp b/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp index 8291e479..1a51f6b6 100644 --- a/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp +++ b/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp @@ -47,9 +47,9 @@ int main(int argc, char** argv) " websocket-client-sync-ssl echo.websocket.org 443 \"Hello, world!\"\n"; return EXIT_FAILURE; } - auto const host = argv[1]; - auto const port = argv[2]; - auto const text = argv[3]; + std::string host = argv[1]; + auto const port = argv[2]; + auto const text = argv[3]; // The io_context is required for all I/O net::io_context ioc; @@ -68,7 +68,12 @@ int main(int argc, char** argv) auto const results = resolver.resolve(host, port); // Make the connection on the IP address we get from a lookup - net::connect(ws.next_layer().next_layer(), results.begin(), results.end()); + auto ep = net::connect(get_lowest_layer(ws), results); + + // Update the host_ string. This will provide the value of the + // Host HTTP header during the WebSocket handshake. + // See https://tools.ietf.org/html/rfc7230#section-5.4 + host += ':' + std::to_string(ep.port()); // Perform the SSL handshake ws.next_layer().handshake(ssl::stream_base::client); diff --git a/example/websocket/client/sync/websocket_client_sync.cpp b/example/websocket/client/sync/websocket_client_sync.cpp index c80ae41b..07409b70 100644 --- a/example/websocket/client/sync/websocket_client_sync.cpp +++ b/example/websocket/client/sync/websocket_client_sync.cpp @@ -43,9 +43,9 @@ int main(int argc, char** argv) " websocket-client-sync echo.websocket.org 80 \"Hello, world!\"\n"; return EXIT_FAILURE; } - auto const host = argv[1]; - auto const port = argv[2]; - auto const text = argv[3]; + std::string host = argv[1]; + auto const port = argv[2]; + auto const text = argv[3]; // The io_context is required for all I/O net::io_context ioc; @@ -58,7 +58,12 @@ int main(int argc, char** argv) auto const results = resolver.resolve(host, port); // Make the connection on the IP address we get from a lookup - net::connect(ws.next_layer(), results.begin(), results.end()); + auto ep = net::connect(ws.next_layer(), results); + + // Update the host_ string. This will provide the value of the + // Host HTTP header during the WebSocket handshake. + // See https://tools.ietf.org/html/rfc7230#section-5.4 + host += ':' + std::to_string(ep.port()); // Set a decorator to change the User-Agent of the handshake ws.set_option(websocket::stream_base::decorator(