Added SimpleWeb::error, and simplified request size checks on server

This commit is contained in:
eidheim 2019-06-23 20:18:28 +02:00
commit 31e6819b42
6 changed files with 39 additions and 38 deletions

View file

@ -7,6 +7,7 @@
#include <asio.hpp>
#include <asio/steady_timer.hpp>
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 <boost/asio/steady_timer.hpp>
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;

View file

@ -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<Response> request(const std::string &method, const std::string &path = {"/"}, string_view content = {}, const CaseInsensitiveMultimap &header = {}) {
std::shared_ptr<Response> 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<Response> request(const std::string &method, const std::string &path, std::istream &content, const CaseInsensitiveMultimap &header = {}) {
std::shared_ptr<Response> 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<void(std::shared_ptr<Response>, const error_code &)> &&request_callback_) {
auto session = std::make_shared<Session>(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<void(std::shared_ptr<Response>, 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<void(std::shared_ptr<Response>, 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<void(std::shared_ptr<Response>, 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<void(std::shared_ptr<Response>, const error_code &)> &&request_callback_) {
auto session = std::make_shared<Session>(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<void(std::shared_ptr<Response>, 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<std::mutex> lock(connections_mutex);
auto it = connections.find(session->connection);
if(it != connections.end()) {

View file

@ -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));

View file

@ -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<Response>(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<Response>(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<Response>(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<Response>(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<Response>(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<Response>(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<Session>(config.max_request_streambuf_size, connection);

View file

@ -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<Session>(config.max_request_streambuf_size, connection);

View file

@ -3,10 +3,6 @@
#include "server_http.hpp"
#include <future>
#ifndef USE_STANDALONE_ASIO
namespace asio = boost::asio;
#endif
using namespace std;
using HttpServer = SimpleWeb::Server<SimpleWeb::HTTP>;
@ -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;
});