Rename HttpConnection to HttpSession; refine error messages.
This commit is contained in:
@@ -12,7 +12,7 @@ set(HEADERS
|
|||||||
globals.h
|
globals.h
|
||||||
http_async_client.h
|
http_async_client.h
|
||||||
http_client.h
|
http_client.h
|
||||||
http_connection.h
|
http_session.h
|
||||||
http_message.h
|
http_message.h
|
||||||
http_parser.h
|
http_parser.h
|
||||||
http_request.h
|
http_request.h
|
||||||
@@ -37,7 +37,7 @@ set(SOURCES
|
|||||||
globals.cc
|
globals.cc
|
||||||
http_async_client.cc
|
http_async_client.cc
|
||||||
http_client.cc
|
http_client.cc
|
||||||
http_connection.cc
|
http_session.cc
|
||||||
http_message.cc
|
http_message.cc
|
||||||
http_parser.cc
|
http_parser.cc
|
||||||
http_request.cc
|
http_request.cc
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@
|
|||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
// Explicitly declare the copy constructor and assignment operator as deleted.
|
// Explicitly declare the copy constructor and assignment operator as deleted.
|
||||||
#define DELETE_COPY_AND_ASSIGN(TypeName) \
|
#define WEBCC_DELETE_COPY_ASSIGN(TypeName) \
|
||||||
TypeName(const TypeName&) = delete; \
|
TypeName(const TypeName&) = delete; \
|
||||||
TypeName& operator=(const TypeName&) = delete;
|
TypeName& operator=(const TypeName&) = delete;
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ void HttpAsyncClient::Request(std::shared_ptr<HttpRequest> request,
|
|||||||
response_.reset(new HttpResponse());
|
response_.reset(new HttpResponse());
|
||||||
response_parser_.reset(new HttpResponseParser(response_.get()));
|
response_parser_.reset(new HttpResponseParser(response_.get()));
|
||||||
|
|
||||||
stopped_ = timed_out_ = false;
|
stopped_ = false;
|
||||||
|
timed_out_ = false;
|
||||||
|
|
||||||
LOG_VERB("HTTP request:\n%s", request->Dump(4, "> ").c_str());
|
LOG_VERB("HTTP request:\n%s", request->Dump(4, "> ").c_str());
|
||||||
|
|
||||||
@@ -42,7 +43,10 @@ void HttpAsyncClient::Request(std::shared_ptr<HttpRequest> request,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HttpAsyncClient::Stop() {
|
void HttpAsyncClient::Stop() {
|
||||||
if (!stopped_) {
|
if (stopped_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
stopped_ = true;
|
stopped_ = true;
|
||||||
|
|
||||||
LOG_INFO("Close socket...");
|
LOG_INFO("Close socket...");
|
||||||
@@ -50,12 +54,11 @@ void HttpAsyncClient::Stop() {
|
|||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
socket_.close(ec);
|
socket_.close(ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
LOG_ERRO("Failed to close socket.");
|
LOG_ERRO("Socket close error (%s).", ec.message().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("Cancel deadline timer...");
|
LOG_INFO("Cancel deadline timer...");
|
||||||
deadline_.cancel();
|
deadline_.cancel();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpAsyncClient::OnResolve(boost::system::error_code ec,
|
void HttpAsyncClient::OnResolve(boost::system::error_code ec,
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class HttpAsyncClient : public std::enable_shared_from_this<HttpAsyncClient> {
|
|||||||
public:
|
public:
|
||||||
explicit HttpAsyncClient(boost::asio::io_context& io_context);
|
explicit HttpAsyncClient(boost::asio::io_context& io_context);
|
||||||
|
|
||||||
DELETE_COPY_AND_ASSIGN(HttpAsyncClient);
|
WEBCC_DELETE_COPY_ASSIGN(HttpAsyncClient);
|
||||||
|
|
||||||
void set_timeout_seconds(int timeout_seconds) {
|
void set_timeout_seconds(int timeout_seconds) {
|
||||||
timeout_seconds_ = timeout_seconds;
|
timeout_seconds_ = timeout_seconds;
|
||||||
|
|||||||
@@ -7,8 +7,6 @@
|
|||||||
#include "boost/asio/read.hpp"
|
#include "boost/asio/read.hpp"
|
||||||
#include "boost/asio/write.hpp"
|
#include "boost/asio/write.hpp"
|
||||||
#include "boost/date_time/posix_time/posix_time.hpp"
|
#include "boost/date_time/posix_time/posix_time.hpp"
|
||||||
#include "boost/lambda/bind.hpp"
|
|
||||||
#include "boost/lambda/lambda.hpp"
|
|
||||||
|
|
||||||
#include "webcc/logger.h"
|
#include "webcc/logger.h"
|
||||||
#include "webcc/utility.h"
|
#include "webcc/utility.h"
|
||||||
@@ -67,7 +65,7 @@ Error HttpClient::Connect(const HttpRequest& request) {
|
|||||||
auto endpoints = resolver.resolve(tcp::v4(), request.host(), port, ec);
|
auto endpoints = resolver.resolve(tcp::v4(), request.host(), port, ec);
|
||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
LOG_ERRO("Can't resolve host (%s): %s, %s", ec.message().c_str(),
|
LOG_ERRO("Host resolve error (%s): %s, %s.", ec.message().c_str(),
|
||||||
request.host().c_str(), port.c_str());
|
request.host().c_str(), port.c_str());
|
||||||
return kHostResolveError;
|
return kHostResolveError;
|
||||||
}
|
}
|
||||||
@@ -219,7 +217,10 @@ void HttpClient::OnDeadline(boost::system::error_code ec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HttpClient::Stop() {
|
void HttpClient::Stop() {
|
||||||
if (!stopped_) {
|
if (stopped_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
stopped_ = true;
|
stopped_ = true;
|
||||||
|
|
||||||
LOG_INFO("Close socket...");
|
LOG_INFO("Close socket...");
|
||||||
@@ -227,12 +228,11 @@ void HttpClient::Stop() {
|
|||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
socket_.close(ec);
|
socket_.close(ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
LOG_ERRO("Failed to close socket.");
|
LOG_ERRO("Socket close error (%s).", ec.message().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("Cancel deadline timer...");
|
LOG_INFO("Cancel deadline timer...");
|
||||||
deadline_.cancel();
|
deadline_.cancel();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webcc
|
} // namespace webcc
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ class HttpClient {
|
|||||||
HttpClient();
|
HttpClient();
|
||||||
~HttpClient() = default;
|
~HttpClient() = default;
|
||||||
|
|
||||||
DELETE_COPY_AND_ASSIGN(HttpClient);
|
WEBCC_DELETE_COPY_ASSIGN(HttpClient);
|
||||||
|
|
||||||
// Set the timeout seconds for reading response.
|
// Set the timeout seconds for reading response.
|
||||||
// The |seconds| is only effective when greater than 0.
|
// The |seconds| is only effective when greater than 0.
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ class HttpParser {
|
|||||||
|
|
||||||
virtual ~HttpParser() = default;
|
virtual ~HttpParser() = default;
|
||||||
|
|
||||||
DELETE_COPY_AND_ASSIGN(HttpParser);
|
WEBCC_DELETE_COPY_ASSIGN(HttpParser);
|
||||||
|
|
||||||
bool finished() const { return finished_; }
|
bool finished() const { return finished_; }
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
void HttpRequestHandler::Enqueue(HttpConnectionPtr connection) {
|
void HttpRequestHandler::Enqueue(HttpSessionPtr session) {
|
||||||
queue_.Push(connection);
|
queue_.Push(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpRequestHandler::Start(std::size_t count) {
|
void HttpRequestHandler::Start(std::size_t count) {
|
||||||
@@ -24,14 +24,14 @@ void HttpRequestHandler::Start(std::size_t count) {
|
|||||||
void HttpRequestHandler::Stop() {
|
void HttpRequestHandler::Stop() {
|
||||||
LOG_INFO("Stopping workers...");
|
LOG_INFO("Stopping workers...");
|
||||||
|
|
||||||
// Close pending connections.
|
// Close pending sessions.
|
||||||
for (HttpConnectionPtr conn = queue_.Pop(); conn; conn = queue_.Pop()) {
|
for (HttpSessionPtr s = queue_.Pop(); s; s = queue_.Pop()) {
|
||||||
LOG_INFO("Closing pending connection...");
|
LOG_INFO("Closing pending session...");
|
||||||
conn->Close();
|
s->Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enqueue a null connection to trigger the first worker to stop.
|
// Enqueue a null session to trigger the first worker to stop.
|
||||||
queue_.Push(HttpConnectionPtr());
|
queue_.Push(HttpSessionPtr());
|
||||||
|
|
||||||
for (auto& worker : workers_) {
|
for (auto& worker : workers_) {
|
||||||
if (worker.joinable()) {
|
if (worker.joinable()) {
|
||||||
@@ -46,19 +46,19 @@ void HttpRequestHandler::WorkerRoutine() {
|
|||||||
LOG_INFO("Worker is running.");
|
LOG_INFO("Worker is running.");
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
HttpConnectionPtr connection = queue_.PopOrWait();
|
HttpSessionPtr session = queue_.PopOrWait();
|
||||||
|
|
||||||
if (!connection) {
|
if (!session) {
|
||||||
LOG_INFO("Worker is going to stop.");
|
LOG_INFO("Worker is going to stop.");
|
||||||
|
|
||||||
// For stopping next worker.
|
// For stopping next worker.
|
||||||
queue_.Push(HttpConnectionPtr());
|
queue_.Push(HttpSessionPtr());
|
||||||
|
|
||||||
// Stop the worker.
|
// Stop the worker.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleConnection(connection);
|
HandleSession(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "webcc/http_connection.h"
|
#include "webcc/http_session.h"
|
||||||
#include "webcc/queue.h"
|
#include "webcc/queue.h"
|
||||||
#include "webcc/soap_service.h"
|
#include "webcc/soap_service.h"
|
||||||
|
|
||||||
@@ -20,24 +20,24 @@ class HttpRequestHandler {
|
|||||||
HttpRequestHandler() = default;
|
HttpRequestHandler() = default;
|
||||||
virtual ~HttpRequestHandler() = default;
|
virtual ~HttpRequestHandler() = default;
|
||||||
|
|
||||||
DELETE_COPY_AND_ASSIGN(HttpRequestHandler);
|
WEBCC_DELETE_COPY_ASSIGN(HttpRequestHandler);
|
||||||
|
|
||||||
// Put the connection into the queue.
|
// Put the session into the queue.
|
||||||
void Enqueue(HttpConnectionPtr connection);
|
void Enqueue(HttpSessionPtr session);
|
||||||
|
|
||||||
// Start worker threads.
|
// Start worker threads.
|
||||||
void Start(std::size_t count);
|
void Start(std::size_t count);
|
||||||
|
|
||||||
// Close pending connections and stop worker threads.
|
// Close pending sessions and stop worker threads.
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void WorkerRoutine();
|
void WorkerRoutine();
|
||||||
|
|
||||||
// Called by the worker routine.
|
// Called by the worker routine.
|
||||||
virtual void HandleConnection(HttpConnectionPtr connection) = 0;
|
virtual void HandleSession(HttpSessionPtr session) = 0;
|
||||||
|
|
||||||
Queue<HttpConnectionPtr> queue_;
|
Queue<HttpSessionPtr> queue_;
|
||||||
std::vector<std::thread> workers_;
|
std::vector<std::thread> workers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ HttpServer::HttpServer(std::uint16_t port, std::size_t workers)
|
|||||||
// Open the acceptor.
|
// Open the acceptor.
|
||||||
acceptor_.open(endpoint.protocol(), ec);
|
acceptor_.open(endpoint.protocol(), ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
LOG_ERRO("Acceptor open error: %s", ec.message().c_str());
|
LOG_ERRO("Acceptor open error (%s).", ec.message().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ HttpServer::HttpServer(std::uint16_t port, std::size_t workers)
|
|||||||
// Bind to the server address.
|
// Bind to the server address.
|
||||||
acceptor_.bind(endpoint, ec);
|
acceptor_.bind(endpoint, ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
LOG_ERRO("Acceptor bind error: %s", ec.message().c_str());
|
LOG_ERRO("Acceptor bind error (%s).", ec.message().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ HttpServer::HttpServer(std::uint16_t port, std::size_t workers)
|
|||||||
// has not started to accept the connection yet.
|
// has not started to accept the connection yet.
|
||||||
acceptor_.listen(boost::asio::socket_base::max_listen_connections, ec);
|
acceptor_.listen(boost::asio::socket_base::max_listen_connections, ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
LOG_ERRO("Acceptor listen error: %s", ec.message().c_str());
|
LOG_ERRO("Acceptor listen error (%s).", ec.message().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,7 +96,7 @@ void HttpServer::DoAccept() {
|
|||||||
if (!ec) {
|
if (!ec) {
|
||||||
LOG_INFO("Accepted a connection.");
|
LOG_INFO("Accepted a connection.");
|
||||||
|
|
||||||
std::make_shared<HttpConnection>(std::move(socket),
|
std::make_shared<HttpSession>(std::move(socket),
|
||||||
GetRequestHandler())->Start();
|
GetRequestHandler())->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -8,7 +8,7 @@
|
|||||||
#include "boost/asio/signal_set.hpp"
|
#include "boost/asio/signal_set.hpp"
|
||||||
|
|
||||||
#include "webcc/globals.h"
|
#include "webcc/globals.h"
|
||||||
#include "webcc/http_connection.h"
|
#include "webcc/http_session.h"
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ class HttpServer {
|
|||||||
|
|
||||||
virtual ~HttpServer() = default;
|
virtual ~HttpServer() = default;
|
||||||
|
|
||||||
DELETE_COPY_AND_ASSIGN(HttpServer);
|
WEBCC_DELETE_COPY_ASSIGN(HttpServer);
|
||||||
|
|
||||||
// Run the server's io_service loop.
|
// Run the server's io_service loop.
|
||||||
void Run();
|
void Run();
|
||||||
|
|||||||
@@ -1,61 +1,59 @@
|
|||||||
#include "webcc/http_connection.h"
|
#include "webcc/http_session.h"
|
||||||
|
|
||||||
#include <utility> // for move()
|
#include <utility> // for move()
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "boost/asio/write.hpp"
|
#include "boost/asio/write.hpp"
|
||||||
#include "boost/date_time/posix_time/posix_time.hpp"
|
|
||||||
|
|
||||||
#include "webcc/http_request_handler.h"
|
#include "webcc/http_request_handler.h"
|
||||||
#include "webcc/logger.h"
|
#include "webcc/logger.h"
|
||||||
|
|
||||||
|
using boost::asio::ip::tcp;
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
HttpConnection::HttpConnection(boost::asio::ip::tcp::socket socket,
|
HttpSession::HttpSession(tcp::socket socket, HttpRequestHandler* handler)
|
||||||
HttpRequestHandler* handler)
|
|
||||||
: socket_(std::move(socket)),
|
: socket_(std::move(socket)),
|
||||||
buffer_(kBufferSize),
|
buffer_(kBufferSize),
|
||||||
request_handler_(handler),
|
request_handler_(handler),
|
||||||
request_parser_(&request_) {
|
request_parser_(&request_) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpConnection::Start() {
|
void HttpSession::Start() {
|
||||||
DoRead();
|
DoRead();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpConnection::Close() {
|
void HttpSession::Close() {
|
||||||
LOG_INFO("Close socket...");
|
LOG_INFO("Close socket...");
|
||||||
|
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
socket_.close(ec);
|
socket_.close(ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
LOG_ERRO("Failed to close socket.");
|
LOG_ERRO("Socket close error (%s).", ec.message().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpConnection::SetResponseContent(std::string&& content,
|
void HttpSession::SetResponseContent(std::string&& content,
|
||||||
const std::string& type) {
|
const std::string& type) {
|
||||||
response_.SetContent(std::move(content), true);
|
response_.SetContent(std::move(content), true);
|
||||||
response_.SetContentType(type);
|
response_.SetContentType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpConnection::SendResponse(HttpStatus::Enum status) {
|
void HttpSession::SendResponse(HttpStatus::Enum status) {
|
||||||
response_.set_status(status);
|
response_.set_status(status);
|
||||||
response_.UpdateStartLine();
|
response_.UpdateStartLine();
|
||||||
DoWrite();
|
DoWrite();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpConnection::DoRead() {
|
void HttpSession::DoRead() {
|
||||||
socket_.async_read_some(boost::asio::buffer(buffer_),
|
socket_.async_read_some(boost::asio::buffer(buffer_),
|
||||||
std::bind(&HttpConnection::OnRead,
|
std::bind(&HttpSession::OnRead, shared_from_this(),
|
||||||
shared_from_this(),
|
|
||||||
std::placeholders::_1,
|
std::placeholders::_1,
|
||||||
std::placeholders::_2));
|
std::placeholders::_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpConnection::OnRead(boost::system::error_code ec,
|
void HttpSession::OnRead(boost::system::error_code ec, std::size_t length) {
|
||||||
std::size_t length) {
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
LOG_ERRO("Socket read error: %s", ec.message().c_str());
|
LOG_ERRO("Socket read error (%s).", ec.message().c_str());
|
||||||
if (ec != boost::asio::error::operation_aborted) {
|
if (ec != boost::asio::error::operation_aborted) {
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
@@ -78,18 +76,16 @@ void HttpConnection::OnRead(boost::system::error_code ec,
|
|||||||
|
|
||||||
LOG_VERB("HTTP request:\n%s", request_.Dump(4, "> ").c_str());
|
LOG_VERB("HTTP request:\n%s", request_.Dump(4, "> ").c_str());
|
||||||
|
|
||||||
// Enqueue this connection.
|
// Enqueue this session.
|
||||||
// Some worker thread will handle it later.
|
// Some worker thread will handle it later.
|
||||||
request_handler_->Enqueue(shared_from_this());
|
request_handler_->Enqueue(shared_from_this());
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpConnection::DoWrite() {
|
void HttpSession::DoWrite() {
|
||||||
LOG_VERB("HTTP response:\n%s", response_.Dump(4, "> ").c_str());
|
LOG_VERB("HTTP response:\n%s", response_.Dump(4, "> ").c_str());
|
||||||
|
|
||||||
boost::asio::async_write(socket_,
|
boost::asio::async_write(socket_, response_.ToBuffers(),
|
||||||
response_.ToBuffers(),
|
std::bind(&HttpSession::OnWrite, shared_from_this(),
|
||||||
std::bind(&HttpConnection::OnWrite,
|
|
||||||
shared_from_this(),
|
|
||||||
std::placeholders::_1,
|
std::placeholders::_1,
|
||||||
std::placeholders::_2));
|
std::placeholders::_2));
|
||||||
}
|
}
|
||||||
@@ -98,10 +94,9 @@ void HttpConnection::DoWrite() {
|
|||||||
// This write handler will be called from main thread (the thread calling
|
// This write handler will be called from main thread (the thread calling
|
||||||
// io_context.run), even though AsyncWrite() is invoked by worker threads.
|
// io_context.run), even though AsyncWrite() is invoked by worker threads.
|
||||||
// This is ensured by Asio.
|
// This is ensured by Asio.
|
||||||
void HttpConnection::OnWrite(boost::system::error_code ec,
|
void HttpSession::OnWrite(boost::system::error_code ec, std::size_t length) {
|
||||||
std::size_t length) {
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
LOG_ERRO("Socket write error: %s", ec.message().c_str());
|
LOG_ERRO("Socket write error (%s).", ec.message().c_str());
|
||||||
|
|
||||||
if (ec != boost::asio::error::operation_aborted) {
|
if (ec != boost::asio::error::operation_aborted) {
|
||||||
Close();
|
Close();
|
||||||
@@ -114,17 +109,17 @@ void HttpConnection::OnWrite(boost::system::error_code ec,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Socket close VS. Shutdown:
|
// Socket close VS. shutdown:
|
||||||
// https://stackoverflow.com/questions/4160347/close-vs-shutdown-socket
|
// https://stackoverflow.com/questions/4160347/close-vs-shutdown-socket
|
||||||
void HttpConnection::Shutdown() {
|
void HttpSession::Shutdown() {
|
||||||
LOG_INFO("Shutdown socket...");
|
LOG_INFO("Shutdown socket...");
|
||||||
|
|
||||||
// Initiate graceful connection closure.
|
// Initiate graceful connection closure.
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
|
socket_.shutdown(tcp::socket::shutdown_both, ec);
|
||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
LOG_ERRO("Socket shutdown error: %s", ec.message().c_str());
|
LOG_ERRO("Socket shutdown error (%s).", ec.message().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef WEBCC_HTTP_CONNECTION_H_
|
#ifndef WEBCC_HTTP_SESSION_H_
|
||||||
#define WEBCC_HTTP_CONNECTION_H_
|
#define WEBCC_HTTP_SESSION_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -16,14 +16,14 @@ namespace webcc {
|
|||||||
|
|
||||||
class HttpRequestHandler;
|
class HttpRequestHandler;
|
||||||
|
|
||||||
class HttpConnection : public std::enable_shared_from_this<HttpConnection> {
|
class HttpSession : public std::enable_shared_from_this<HttpSession> {
|
||||||
public:
|
public:
|
||||||
HttpConnection(boost::asio::ip::tcp::socket socket, // Will be moved
|
HttpSession(boost::asio::ip::tcp::socket socket,
|
||||||
HttpRequestHandler* handler);
|
HttpRequestHandler* handler);
|
||||||
|
|
||||||
~HttpConnection() = default;
|
~HttpSession() = default;
|
||||||
|
|
||||||
DELETE_COPY_AND_ASSIGN(HttpConnection);
|
WEBCC_DELETE_COPY_ASSIGN(HttpSession);
|
||||||
|
|
||||||
const HttpRequest& request() const { return request_; }
|
const HttpRequest& request() const { return request_; }
|
||||||
|
|
||||||
@@ -67,8 +67,8 @@ class HttpConnection : public std::enable_shared_from_this<HttpConnection> {
|
|||||||
HttpResponse response_;
|
HttpResponse response_;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<HttpConnection> HttpConnectionPtr;
|
typedef std::shared_ptr<HttpSession> HttpSessionPtr;
|
||||||
|
|
||||||
} // namespace webcc
|
} // namespace webcc
|
||||||
|
|
||||||
#endif // WEBCC_HTTP_CONNECTION_H_
|
#endif // WEBCC_HTTP_SESSION_H_
|
||||||
+1
-1
@@ -19,7 +19,7 @@ class RestClient {
|
|||||||
|
|
||||||
~RestClient() = default;
|
~RestClient() = default;
|
||||||
|
|
||||||
DELETE_COPY_AND_ASSIGN(RestClient);
|
WEBCC_DELETE_COPY_ASSIGN(RestClient);
|
||||||
|
|
||||||
void SetTimeout(int seconds) {
|
void SetTimeout(int seconds) {
|
||||||
http_client_.SetTimeout(seconds);
|
http_client_.SetTimeout(seconds);
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ bool RestRequestHandler::Bind(RestServicePtr service, const std::string& url,
|
|||||||
return service_manager_.AddService(service, url, is_regex);
|
return service_manager_.AddService(service, url, is_regex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RestRequestHandler::HandleConnection(HttpConnectionPtr connection) {
|
void RestRequestHandler::HandleSession(HttpSessionPtr session) {
|
||||||
const HttpRequest& http_request = connection->request();
|
const HttpRequest& http_request = session->request();
|
||||||
|
|
||||||
Url url(http_request.url(), /*decode*/true);
|
Url url(http_request.url(), /*decode*/true);
|
||||||
|
|
||||||
if (!url.IsValid()) {
|
if (!url.IsValid()) {
|
||||||
connection->SendResponse(HttpStatus::kBadRequest);
|
session->SendResponse(HttpStatus::kBadRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,12 +28,12 @@ void RestRequestHandler::HandleConnection(HttpConnectionPtr connection) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Get service by URL path.
|
// Get service by URL path.
|
||||||
RestServicePtr service = service_manager_.GetService(
|
RestServicePtr service =
|
||||||
url.path(), &rest_request.url_sub_matches);
|
service_manager_.GetService(url.path(), &rest_request.url_sub_matches);
|
||||||
|
|
||||||
if (!service) {
|
if (!service) {
|
||||||
LOG_WARN("No service matches the URL path: %s", url.path().c_str());
|
LOG_WARN("No service matches the URL path: %s", url.path().c_str());
|
||||||
connection->SendResponse(HttpStatus::kNotFound);
|
session->SendResponse(HttpStatus::kNotFound);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,12 +41,12 @@ void RestRequestHandler::HandleConnection(HttpConnectionPtr connection) {
|
|||||||
service->Handle(rest_request, &rest_response);
|
service->Handle(rest_request, &rest_response);
|
||||||
|
|
||||||
if (!rest_response.content.empty()) {
|
if (!rest_response.content.empty()) {
|
||||||
connection->SetResponseContent(std::move(rest_response.content),
|
session->SetResponseContent(std::move(rest_response.content),
|
||||||
kAppJsonUtf8);
|
kAppJsonUtf8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send response back to client.
|
// Send response back to client.
|
||||||
connection->SendResponse(rest_response.status);
|
session->SendResponse(rest_response.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webcc
|
} // namespace webcc
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class RestRequestHandler : public HttpRequestHandler {
|
|||||||
bool Bind(RestServicePtr service, const std::string& url, bool is_regex);
|
bool Bind(RestServicePtr service, const std::string& url, bool is_regex);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void HandleConnection(HttpConnectionPtr connection) override;
|
void HandleSession(HttpSessionPtr session) override;
|
||||||
|
|
||||||
RestServiceManager service_manager_;
|
RestServiceManager service_manager_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class RestServiceManager {
|
|||||||
public:
|
public:
|
||||||
RestServiceManager() = default;
|
RestServiceManager() = default;
|
||||||
|
|
||||||
DELETE_COPY_AND_ASSIGN(RestServiceManager);
|
WEBCC_DELETE_COPY_ASSIGN(RestServiceManager);
|
||||||
|
|
||||||
// Add a service and bind it with the given URL.
|
// Add a service and bind it with the given URL.
|
||||||
// The |url| should start with "/" and will be treated as a regular expression
|
// The |url| should start with "/" and will be treated as a regular expression
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class SoapAsyncClient {
|
|||||||
|
|
||||||
~SoapAsyncClient() = default;
|
~SoapAsyncClient() = default;
|
||||||
|
|
||||||
DELETE_COPY_AND_ASSIGN(SoapAsyncClient);
|
WEBCC_DELETE_COPY_ASSIGN(SoapAsyncClient);
|
||||||
|
|
||||||
void set_timeout_seconds(int timeout_seconds) {
|
void set_timeout_seconds(int timeout_seconds) {
|
||||||
timeout_seconds_ = timeout_seconds;
|
timeout_seconds_ = timeout_seconds;
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ class SoapClient {
|
|||||||
|
|
||||||
~SoapClient() = default;
|
~SoapClient() = default;
|
||||||
|
|
||||||
DELETE_COPY_AND_ASSIGN(SoapClient);
|
WEBCC_DELETE_COPY_ASSIGN(SoapClient);
|
||||||
|
|
||||||
void SetTimeout(int seconds) {
|
void SetTimeout(int seconds) {
|
||||||
http_client_.SetTimeout(seconds);
|
http_client_.SetTimeout(seconds);
|
||||||
|
|||||||
@@ -15,30 +15,30 @@ bool SoapRequestHandler::Bind(SoapServicePtr service, const std::string& url) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoapRequestHandler::HandleConnection(HttpConnectionPtr connection) {
|
void SoapRequestHandler::HandleSession(HttpSessionPtr session) {
|
||||||
SoapServicePtr service = GetServiceByUrl(connection->request().url());
|
SoapServicePtr service = GetServiceByUrl(session->request().url());
|
||||||
if (!service) {
|
if (!service) {
|
||||||
connection->SendResponse(HttpStatus::kBadRequest);
|
session->SendResponse(HttpStatus::kBadRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the SOAP request XML.
|
// Parse the SOAP request XML.
|
||||||
SoapRequest soap_request;
|
SoapRequest soap_request;
|
||||||
if (!soap_request.FromXml(connection->request().content())) {
|
if (!soap_request.FromXml(session->request().content())) {
|
||||||
connection->SendResponse(HttpStatus::kBadRequest);
|
session->SendResponse(HttpStatus::kBadRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SoapResponse soap_response;
|
SoapResponse soap_response;
|
||||||
if (!service->Handle(soap_request, &soap_response)) {
|
if (!service->Handle(soap_request, &soap_response)) {
|
||||||
connection->SendResponse(HttpStatus::kBadRequest);
|
session->SendResponse(HttpStatus::kBadRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string content;
|
std::string content;
|
||||||
soap_response.ToXml(format_raw_, indent_str_, &content);
|
soap_response.ToXml(format_raw_, indent_str_, &content);
|
||||||
connection->SetResponseContent(std::move(content), kTextXmlUtf8);
|
session->SetResponseContent(std::move(content), kTextXmlUtf8);
|
||||||
connection->SendResponse(HttpStatus::kOK);
|
session->SendResponse(HttpStatus::kOK);
|
||||||
}
|
}
|
||||||
|
|
||||||
SoapServicePtr SoapRequestHandler::GetServiceByUrl(const std::string& url) {
|
SoapServicePtr SoapRequestHandler::GetServiceByUrl(const std::string& url) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class SoapRequestHandler : public HttpRequestHandler {
|
|||||||
bool Bind(SoapServicePtr service, const std::string& url);
|
bool Bind(SoapServicePtr service, const std::string& url);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void HandleConnection(HttpConnectionPtr connection) override;
|
void HandleSession(HttpSessionPtr session) override;
|
||||||
|
|
||||||
SoapServicePtr GetServiceByUrl(const std::string& url);
|
SoapServicePtr GetServiceByUrl(const std::string& url);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user