From 31e6819b421c0e96321bb583a1d46e1f945aca68 Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 23 Jun 2019 20:18:28 +0200 Subject: [PATCH] Added SimpleWeb::error, and simplified request size checks on server --- asio_compatibility.hpp | 2 ++ client_http.hpp | 20 +++++++++---------- client_https.hpp | 3 ++- server_http.hpp | 44 ++++++++++++++++++++++-------------------- server_https.hpp | 2 +- tests/io_test.cpp | 6 +----- 6 files changed, 39 insertions(+), 38 deletions(-) diff --git a/asio_compatibility.hpp b/asio_compatibility.hpp index 8b6c7ed..d37e348 100644 --- a/asio_compatibility.hpp +++ b/asio_compatibility.hpp @@ -7,6 +7,7 @@ #include #include namespace SimpleWeb { + namespace error = asio::error; using error_code = std::error_code; using errc = std::errc; using system_error = std::system_error; @@ -17,6 +18,7 @@ namespace SimpleWeb { #include namespace SimpleWeb { namespace asio = boost::asio; + namespace error = asio::error; using error_code = boost::system::error_code; namespace errc = boost::system::errc; using system_error = boost::system::system_error; diff --git a/client_http.hpp b/client_http.hpp index 68e1639..2ad46c1 100644 --- a/client_http.hpp +++ b/client_http.hpp @@ -149,7 +149,7 @@ namespace SimpleWeb { /// Convenience function to perform synchronous request. The io_service is run within this function. /// If reusing the io_service for other tasks, use the asynchronous request functions instead. /// Do not use concurrently with the asynchronous request functions. - /// When requesting Server-Sent Events: will throw on asio::error::eof, please use asynchronous request functions instead. + /// When requesting Server-Sent Events: will throw on error::eof, please use asynchronous request functions instead. std::shared_ptr request(const std::string &method, const std::string &path = {"/"}, string_view content = {}, const CaseInsensitiveMultimap &header = {}) { std::shared_ptr response; error_code ec; @@ -179,7 +179,7 @@ namespace SimpleWeb { /// Convenience function to perform synchronous request. The io_service is run within this function. /// If reusing the io_service for other tasks, use the asynchronous request functions instead. /// Do not use concurrently with the asynchronous request functions. - /// When requesting Server-Sent Events: will throw on asio::error::eof, please use asynchronous request functions instead. + /// When requesting Server-Sent Events: will throw on error::eof, please use asynchronous request functions instead. std::shared_ptr request(const std::string &method, const std::string &path, std::istream &content, const CaseInsensitiveMultimap &header = {}) { std::shared_ptr response; error_code ec; @@ -208,7 +208,7 @@ namespace SimpleWeb { /// Asynchronous request where setting and/or running Client's io_service is required. /// Do not use concurrently with the synchronous request functions. - /// When requesting Server-Sent Events: request_callback might be called more than twice, first call with empty contents on open, and with ec = asio::error::eof on last call + /// When requesting Server-Sent Events: request_callback might be called more than twice, first call with empty contents on open, and with ec = error::eof on last call void request(const std::string &method, const std::string &path, string_view content, const CaseInsensitiveMultimap &header, std::function, const error_code &)> &&request_callback_) { auto session = std::make_shared(config.max_response_streambuf_size, get_connection(), create_request_header(method, path, header)); @@ -260,7 +260,7 @@ namespace SimpleWeb { /// Asynchronous request where setting and/or running Client's io_service is required. /// Do not use concurrently with the synchronous request functions. - /// When requesting Server-Sent Events: request_callback might be called more than twice, first call with empty contents on open, and with ec = asio::error::eof on last call + /// When requesting Server-Sent Events: request_callback might be called more than twice, first call with empty contents on open, and with ec = error::eof on last call void request(const std::string &method, const std::string &path, string_view content, std::function, const error_code &)> &&request_callback_) { request(method, path, content, CaseInsensitiveMultimap(), std::move(request_callback_)); @@ -268,7 +268,7 @@ namespace SimpleWeb { /// Asynchronous request where setting and/or running Client's io_service is required. /// Do not use concurrently with the synchronous request functions. - /// When requesting Server-Sent Events: request_callback might be called more than twice, first call with empty contents on open, and with ec = asio::error::eof on last call + /// When requesting Server-Sent Events: request_callback might be called more than twice, first call with empty contents on open, and with ec = error::eof on last call void request(const std::string &method, const std::string &path, std::function, const error_code &)> &&request_callback_) { request(method, path, std::string(), CaseInsensitiveMultimap(), std::move(request_callback_)); @@ -276,14 +276,14 @@ namespace SimpleWeb { /// Asynchronous request where setting and/or running Client's io_service is required. /// Do not use concurrently with the synchronous request functions. - /// When requesting Server-Sent Events: request_callback might be called more than twice, first call with empty contents on open, and with ec = asio::error::eof on last call + /// When requesting Server-Sent Events: request_callback might be called more than twice, first call with empty contents on open, and with ec = error::eof on last call void request(const std::string &method, std::function, const error_code &)> &&request_callback_) { request(method, std::string("/"), std::string(), CaseInsensitiveMultimap(), std::move(request_callback_)); } /// Asynchronous request where setting and/or running Client's io_service is required. /// Do not use concurrently with the synchronous request functions. - /// When requesting Server-Sent Events: request_callback might be called more than twice, first call with empty contents on open, and with ec = asio::error::eof on last call + /// When requesting Server-Sent Events: request_callback might be called more than twice, first call with empty contents on open, and with ec = error::eof on last call void request(const std::string &method, const std::string &path, std::istream &content, const CaseInsensitiveMultimap &header, std::function, const error_code &)> &&request_callback_) { auto session = std::make_shared(config.max_response_streambuf_size, get_connection(), create_request_header(method, path, header)); @@ -339,7 +339,7 @@ namespace SimpleWeb { /// Asynchronous request where setting and/or running Client's io_service is required. /// Do not use concurrently with the synchronous request functions. - /// When requesting Server-Sent Events: request_callback might be called more than twice, first call with empty contents on open, and with ec = asio::error::eof on last call + /// When requesting Server-Sent Events: request_callback might be called more than twice, first call with empty contents on open, and with ec = error::eof on last call void request(const std::string &method, const std::string &path, std::istream &content, std::function, const error_code &)> &&request_callback_) { request(method, path, content, CaseInsensitiveMultimap(), std::move(request_callback_)); @@ -543,7 +543,7 @@ namespace SimpleWeb { session->callback(ec); } else - session->callback(ec == asio::error::eof ? error_code() : ec); + session->callback(ec == error::eof ? error_code() : ec); }); } else if(((header_it = session->response->header.find("Content-Type")) != session->response->header.end() && header_it->second == "text/event-stream")) { @@ -566,7 +566,7 @@ namespace SimpleWeb { session->callback(ec); } else { - if(session->connection->attempt_reconnect && ec != asio::error::operation_aborted) { + if(session->connection->attempt_reconnect && ec != error::operation_aborted) { std::unique_lock lock(connections_mutex); auto it = connections.find(session->connection); if(it != connections.end()) { diff --git a/client_https.hpp b/client_https.hpp index dff5030..ccbb6e2 100644 --- a/client_https.hpp +++ b/client_https.hpp @@ -83,10 +83,11 @@ namespace SimpleWeb { auto lock = session->connection->handler_runner->continue_lock(); if(!lock) return; - if((!ec || ec == asio::error::not_found) && response->streambuf.size() == response->streambuf.max_size()) { + if(response->streambuf.size() == response->streambuf.max_size()) { session->callback(make_error_code::make_error_code(errc::message_size)); return; } + if(!ec) { if(!ResponseMessage::parse(response->content, response->http_version, response->status_code, response->header)) session->callback(make_error_code::make_error_code(errc::protocol_error)); diff --git a/server_http.hpp b/server_http.hpp index 336deef..6b0a3a3 100644 --- a/server_http.hpp +++ b/server_http.hpp @@ -511,13 +511,14 @@ namespace SimpleWeb { if(!lock) return; session->request->header_read_time = std::chrono::system_clock::now(); - if((!ec || ec == asio::error::not_found) && session->request->streambuf.size() == session->request->streambuf.max_size()) { + if(session->request->streambuf.size() == session->request->streambuf.max_size()) { auto response = std::shared_ptr(new Response(session, this->config.timeout_content)); response->write(StatusCode::client_error_payload_too_large); if(this->on_error) this->on_error(session->request, make_error_code::make_error_code(errc::message_size)); return; } + if(!ec) { // request->streambuf.size() is not necessarily the same as bytes_transferred, from Boost-docs: // "After a successful async_read_until operation, the streambuf may contain additional data beyond the delimiter" @@ -551,16 +552,16 @@ namespace SimpleWeb { auto lock = session->connection->handler_runner->continue_lock(); if(!lock) return; - if(!ec) { - if(session->request->streambuf.size() == session->request->streambuf.max_size()) { - auto response = std::shared_ptr(new Response(session, this->config.timeout_content)); - response->write(StatusCode::client_error_payload_too_large); - if(this->on_error) - this->on_error(session->request, make_error_code::make_error_code(errc::message_size)); - return; - } - this->find_resource(session); + if(session->request->streambuf.size() == session->request->streambuf.max_size()) { + auto response = std::shared_ptr(new Response(session, this->config.timeout_content)); + response->write(StatusCode::client_error_payload_too_large); + if(this->on_error) + this->on_error(session->request, make_error_code::make_error_code(errc::message_size)); + return; } + + if(!ec) + this->find_resource(session); else if(this->on_error) this->on_error(session->request, ec); }); @@ -587,13 +588,14 @@ namespace SimpleWeb { auto lock = session->connection->handler_runner->continue_lock(); if(!lock) return; - if((!ec || ec == asio::error::not_found) && session->request->streambuf.size() == session->request->streambuf.max_size()) { + if(session->request->streambuf.size() == session->request->streambuf.max_size()) { auto response = std::shared_ptr(new Response(session, this->config.timeout_content)); response->write(StatusCode::client_error_payload_too_large); if(this->on_error) this->on_error(session->request, make_error_code::make_error_code(errc::message_size)); return; } + if(!ec) { std::string line; getline(session->request->content, line); @@ -618,16 +620,16 @@ namespace SimpleWeb { auto lock = session->connection->handler_runner->continue_lock(); if(!lock) return; - if(!ec) { - if(session->request->streambuf.size() == session->request->streambuf.max_size()) { - auto response = std::shared_ptr(new Response(session, this->config.timeout_content)); - response->write(StatusCode::client_error_payload_too_large); - if(this->on_error) - this->on_error(session->request, make_error_code::make_error_code(errc::message_size)); - return; - } - this->read_chunked_transfer_encoded_chunk(session, chunks_streambuf, length); + if(session->request->streambuf.size() == session->request->streambuf.max_size()) { + auto response = std::shared_ptr(new Response(session, this->config.timeout_content)); + response->write(StatusCode::client_error_payload_too_large); + if(this->on_error) + this->on_error(session->request, make_error_code::make_error_code(errc::message_size)); + return; } + + if(!ec) + this->read_chunked_transfer_encoded_chunk(session, chunks_streambuf, length); else if(this->on_error) this->on_error(session->request, ec); }); @@ -766,7 +768,7 @@ namespace SimpleWeb { return; // Immediately start accepting a new connection (unless io_service has been stopped) - if(ec != asio::error::operation_aborted) + if(ec != error::operation_aborted) this->accept(); auto session = std::make_shared(config.max_request_streambuf_size, connection); diff --git a/server_https.hpp b/server_https.hpp index 0746f4f..b371df5 100644 --- a/server_https.hpp +++ b/server_https.hpp @@ -53,7 +53,7 @@ namespace SimpleWeb { if(!lock) return; - if(ec != asio::error::operation_aborted) + if(ec != error::operation_aborted) this->accept(); auto session = std::make_shared(config.max_request_streambuf_size, connection); diff --git a/tests/io_test.cpp b/tests/io_test.cpp index da71e0e..c5efdb2 100644 --- a/tests/io_test.cpp +++ b/tests/io_test.cpp @@ -3,10 +3,6 @@ #include "server_http.hpp" #include -#ifndef USE_STANDALONE_ASIO -namespace asio = boost::asio; -#endif - using namespace std; using HttpServer = SimpleWeb::Server; @@ -363,7 +359,7 @@ int main() { } else if(call_num == 3) { ASSERT(response->content.string().empty()); - ASSERT(ec == asio::error::eof); + ASSERT(ec == SimpleWeb::error::eof); } ++call_num; });