diff --git a/changelog.md b/changelog.md index 24b9471cba..8158a6a209 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,6 @@ HEAD +- Fixes an issue where custom headers couldn't be set for client connections + Thank you Jerry Win and Wolfram Schroers for reporting. - Fixes a compile error on visual studio when using interrupts. Thank you Javier Rey Neira for reporting this. - Adds new 1012 and 1013 close codes per IANA registry diff --git a/test/connection/connection.cpp b/test/connection/connection.cpp index c8f7db02e1..7b155a99a0 100644 --- a/test/connection/connection.cpp +++ b/test/connection/connection.cpp @@ -174,7 +174,7 @@ BOOST_AUTO_TEST_CASE( basic_client_websocket ) { //std::string output = "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\nServer: foo\r\nUpgrade: websocket\r\n\r\n"; - std::string ref = "GET / HTTP/1.1\r\nConnection: Upgrade\r\nHost: localhost\r\nSec-WebSocket-Key: AAAAAAAAAAAAAAAAAAAAAA==\r\nSec-WebSocket-Version: 13\r\nUpgrade: websocket\r\nUser-Agent: foo\r\n\r\n"; + std::string ref = "GET / HTTP/1.1\r\nConnection: Upgrade\r\nFoo: Bar\r\nHost: localhost\r\nSec-WebSocket-Key: AAAAAAAAAAAAAAAAAAAAAA==\r\nSec-WebSocket-Version: 13\r\nUpgrade: websocket\r\nUser-Agent: foo\r\n\r\n"; std::stringstream output; @@ -187,6 +187,7 @@ BOOST_AUTO_TEST_CASE( basic_client_websocket ) { client::connection_ptr con; websocketpp::lib::error_code ec; con = e.get_connection(uri, ec); + con->append_header("Foo","Bar"); e.connect(con); BOOST_CHECK_EQUAL(ref, output.str()); diff --git a/websocketpp/connection.hpp b/websocketpp/connection.hpp index 702060fe0d..c95c32ca60 100644 --- a/websocketpp/connection.hpp +++ b/websocketpp/connection.hpp @@ -472,7 +472,7 @@ public: * frame::opcode::text */ lib::error_code send(std::string const & payload, frame::opcode::value op = - frame::opcode::TEXT); + frame::opcode::text); /// Send a message (raw array overload) /** @@ -489,7 +489,7 @@ public: * frame::opcode::binary */ lib::error_code send(void const * payload, size_t len, frame::opcode::value - op = frame::opcode::BINARY); + op = frame::opcode::binary); /// Add a message to the outgoing send queue /** @@ -803,7 +803,7 @@ public: * @see replace_header * @see websocketpp::http::parser::append_header */ - void append_header(std::string const &key, std::string const & val); + void append_header(std::string const & key, std::string const & val); /// Replace a header /** diff --git a/websocketpp/endpoint.hpp b/websocketpp/endpoint.hpp index 3d44aef463..cc72a6de85 100644 --- a/websocketpp/endpoint.hpp +++ b/websocketpp/endpoint.hpp @@ -277,8 +277,26 @@ public: void interrupt(connection_hdl hdl, lib::error_code & ec); void interrupt(connection_hdl hdl); + /// Create a message and add it to the outgoing send queue (exception free) + /** + * Convenience method to send a message given a payload string and an opcode + * + * @param [in] hdl The handle identifying the connection to send via. + * @param [in] payload The payload string to generated the message with + * @param [in] op The opcode to generated the message with. + * @param [out] ec A code to fill in for errors + */ void send(connection_hdl hdl, std::string const & payload, frame::opcode::value op, lib::error_code & ec); + /// Create a message and add it to the outgoing send queue + /** + * Convenience method to send a message given a payload string and an opcode + * + * @param [in] hdl The handle identifying the connection to send via. + * @param [in] payload The payload string to generated the message with + * @param [in] op The opcode to generated the message with. + * @param [out] ec A code to fill in for errors + */ void send(connection_hdl hdl, std::string const & payload, frame::opcode::value op); diff --git a/websocketpp/impl/connection_impl.hpp b/websocketpp/impl/connection_impl.hpp index 4b4aa361e5..26a20f494b 100644 --- a/websocketpp/impl/connection_impl.hpp +++ b/websocketpp/impl/connection_impl.hpp @@ -465,8 +465,7 @@ connection::get_response_header(const std::string &key) { } template -void connection::set_status( - http::status_code::value code) +void connection::set_status(http::status_code::value code) { //scoped_lock_type lock(m_connection_state_lock); @@ -479,8 +478,8 @@ void connection::set_status( m_response.set_status(code); } template -void connection::set_status( - http::status_code::value code, const std::string& msg) +void connection::set_status(http::status_code::value code, + std::string const & msg) { //scoped_lock_type lock(m_connection_state_lock); @@ -493,7 +492,7 @@ void connection::set_status( m_response.set_status(code,msg); } template -void connection::set_body(const std::string& value) { +void connection::set_body(std::string const & value) { //scoped_lock_type lock(m_connection_state_lock); if (m_internal_state != istate::PROCESS_HTTP_REQUEST) { @@ -504,47 +503,71 @@ void connection::set_body(const std::string& value) { m_response.set_body(value); } + template -void connection::append_header( - const std::string &key, const std::string &val) +void connection::append_header(std::string const & key, + std::string const & val) { //scoped_lock_type lock(m_connection_state_lock); - if (m_internal_state != istate::PROCESS_HTTP_REQUEST) { - throw error::make_error_code(error::invalid_state); - //throw exception("Call to set_status from invalid state", - // error::INVALID_STATE); + if (m_is_server) { + if (m_internal_state == istate::PROCESS_HTTP_REQUEST) { + // we are setting response headers for an incoming server connection + m_response.append_header(key,val); + } else { + throw error::make_error_code(error::invalid_state); + } + } else { + if (m_internal_state == istate::USER_INIT) { + // we are setting initial headers for an outgoing client connection + m_request.append_header(key,val); + } else { + throw error::make_error_code(error::invalid_state); + } } - - m_response.append_header(key,val); } template -void connection::replace_header( - const std::string &key, const std::string &val) +void connection::replace_header(std::string const & key, + std::string const & val) { // scoped_lock_type lock(m_connection_state_lock); - if (m_internal_state != istate::PROCESS_HTTP_REQUEST) { - throw error::make_error_code(error::invalid_state); - //throw exception("Call to set_status from invalid state", - // error::INVALID_STATE); + if (m_is_server) { + if (m_internal_state == istate::PROCESS_HTTP_REQUEST) { + // we are setting response headers for an incoming server connection + m_response.replace_header(key,val); + } else { + throw error::make_error_code(error::invalid_state); + } + } else { + if (m_internal_state == istate::USER_INIT) { + // we are setting initial headers for an outgoing client connection + m_request.replace_header(key,val); + } else { + throw error::make_error_code(error::invalid_state); + } } - - m_response.replace_header(key,val); } template -void connection::remove_header( - const std::string &key) +void connection::remove_header(std::string const & key) { //scoped_lock_type lock(m_connection_state_lock); - if (m_internal_state != istate::PROCESS_HTTP_REQUEST) { - throw error::make_error_code(error::invalid_state); - //throw exception("Call to set_status from invalid state", - // error::INVALID_STATE); + if (m_is_server) { + if (m_internal_state == istate::PROCESS_HTTP_REQUEST) { + // we are setting response headers for an incoming server connection + m_response.remove_header(key); + } else { + throw error::make_error_code(error::invalid_state); + } + } else { + if (m_internal_state == istate::USER_INIT) { + // we are setting initial headers for an outgoing client connection + m_request.remove_header(key); + } else { + throw error::make_error_code(error::invalid_state); + } } - - m_response.remove_header(key); }