a bit better way to treah handlers
This commit is contained in:
parent
f0d205dee7
commit
3fe6d25448
16 changed files with 291 additions and 95 deletions
|
@ -4,41 +4,74 @@
|
|||
#include "router.h"
|
||||
|
||||
Router::Router():
|
||||
table()
|
||||
{
|
||||
get(),
|
||||
post()
|
||||
{}
|
||||
|
||||
}
|
||||
void Router::addRoute(Handler handler) {
|
||||
std::pair<std::map<std::string, Handler>::const_iterator, bool> result;
|
||||
switch (handler->method) {
|
||||
case Request::Method::get:
|
||||
result = get.emplace(handler->path, std::move(handler));
|
||||
break;
|
||||
case Request::Method::post:
|
||||
result = post.emplace(handler->path, std::move(handler));
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("An attempt to register handler with unsupported method type: " + std::to_string((int)handler->method));
|
||||
}
|
||||
|
||||
void Router::addRoute(const std::string& path, const Handler& handler) {
|
||||
auto result = table.emplace(path, handler);
|
||||
if (!result.second)
|
||||
std::cerr << "could'not add route " + path + " to the routing table";
|
||||
throw std::runtime_error("could'not add route " + handler->path + " to the routing table");
|
||||
}
|
||||
|
||||
void Router::route(const std::string& path, std::unique_ptr<Request> request, Server* server) {
|
||||
auto itr = table.find(path);
|
||||
if (itr == table.end())
|
||||
void Router::route(const std::string& path, std::unique_ptr<Request> request) {
|
||||
std::map<std::string, Handler>::const_iterator itr, end;
|
||||
switch (request->method()) {
|
||||
case Request::Method::get:
|
||||
itr = get.find(path);
|
||||
end = get.end();
|
||||
break;
|
||||
case Request::Method::post:
|
||||
itr = post.find(path);
|
||||
end = post.end();
|
||||
break;
|
||||
default:
|
||||
return handleMethodNotAllowed(path, std::move(request));
|
||||
}
|
||||
|
||||
if (itr == end)
|
||||
return handleNotFound(path, std::move(request));
|
||||
|
||||
try {
|
||||
bool result = itr->second(request.get(), server);
|
||||
if (!result)
|
||||
handleInternalError(std::runtime_error("handler failed to handle the request"), std::move(request));
|
||||
itr->second->handle(*request.get());
|
||||
|
||||
if (request->currentState() != Request::State::responded)
|
||||
handleInternalError(path, std::runtime_error("handler failed to handle the request"), std::move(request));
|
||||
else
|
||||
std::cout << "Success:\t" << path << std::endl;
|
||||
} catch (const std::exception& e) {
|
||||
handleInternalError(e, std::move(request));
|
||||
handleInternalError(path, e, std::move(request));
|
||||
}
|
||||
}
|
||||
|
||||
void Router::handleNotFound(const std::string& path, std::unique_ptr<Request> request) {
|
||||
Response notFound(Response::Status::notFound);
|
||||
Response notFound(*request.get(), Response::Status::notFound);
|
||||
notFound.setBody(std::string("Path \"") + path + "\" was not found");
|
||||
notFound.replyTo(*request.get());
|
||||
std::cerr << "Not found: " << path << std::endl;
|
||||
notFound.send();
|
||||
std::cerr << "Not found:\t" << path << std::endl;
|
||||
}
|
||||
|
||||
void Router::handleInternalError(const std::exception& exception, std::unique_ptr<Request> request) {
|
||||
Response error(Response::Status::internalError);
|
||||
void Router::handleInternalError(const std::string& path, const std::exception& exception, std::unique_ptr<Request> request) {
|
||||
Response error(*request.get(), Response::Status::internalError);
|
||||
error.setBody(std::string(exception.what()));
|
||||
error.replyTo(*request.get());
|
||||
std::cerr << "Internal error: " << exception.what() << std::endl;
|
||||
error.send();
|
||||
std::cerr << "Internal error:\t" << path << "\n\t" << exception.what() << std::endl;
|
||||
}
|
||||
|
||||
void Router::handleMethodNotAllowed(const std::string& path, std::unique_ptr<Request> request) {
|
||||
Response error(*request.get(), Response::Status::methodNotAllowed);
|
||||
error.setBody(std::string("Method not allowed"));
|
||||
error.send();
|
||||
std::cerr << "Method not allowed:\t" << path << std::endl;
|
||||
}
|
||||
|
|
|
@ -10,23 +10,25 @@
|
|||
|
||||
#include "request/request.h"
|
||||
#include "response/response.h"
|
||||
#include "handler/handler.h"
|
||||
|
||||
class Server;
|
||||
|
||||
class Router {
|
||||
using Handler = std::unique_ptr<Handler::Handler>;
|
||||
public:
|
||||
using Handler = std::function<bool(Request*, Server*)>;
|
||||
|
||||
Router();
|
||||
|
||||
void addRoute(const std::string& path, const Handler& handler);
|
||||
void route(const std::string& path, std::unique_ptr<Request> request, Server* server);
|
||||
void addRoute(Handler handler);
|
||||
void route(const std::string& path, std::unique_ptr<Request> request);
|
||||
|
||||
private:
|
||||
void handleNotFound(const std::string& path, std::unique_ptr<Request> request);
|
||||
void handleInternalError(const std::exception& exception, std::unique_ptr<Request> request);
|
||||
void handleInternalError(const std::string& path, const std::exception& exception, std::unique_ptr<Request> request);
|
||||
void handleMethodNotAllowed(const std::string& path, std::unique_ptr<Request> request);
|
||||
|
||||
private:
|
||||
std::map<std::string, Handler> table;
|
||||
std::map<std::string, Handler> get;
|
||||
std::map<std::string, Handler> post;
|
||||
|
||||
};
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
#include "server.h"
|
||||
|
||||
#include "handler/info.h"
|
||||
#include "handler/env.h"
|
||||
|
||||
constexpr uint8_t currentDbVesion = 1;
|
||||
|
||||
Server::Server():
|
||||
|
@ -23,8 +26,8 @@ Server::Server():
|
|||
db->connect("/run/mysqld/mysqld.sock");
|
||||
db->migrate(currentDbVesion);
|
||||
|
||||
router.addRoute("info", Server::info);
|
||||
router.addRoute("env", Server::printEnvironment);
|
||||
router.addRoute(std::make_unique<Handler::Info>());
|
||||
router.addRoute(std::make_unique<Handler::Env>());
|
||||
}
|
||||
|
||||
Server::~Server() {}
|
||||
|
@ -49,49 +52,12 @@ void Server::handleRequest(std::unique_ptr<Request> request) {
|
|||
std::cout << "received server name " << serverName.value() << std::endl;
|
||||
} catch (...) {
|
||||
std::cerr << "failed to read server name" << std::endl;
|
||||
Response error(Response::Status::internalError);
|
||||
error.replyTo(*request.get());
|
||||
Response error(*request.get(), Response::Status::internalError);
|
||||
error.send();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!request->isGet()) {
|
||||
static const Response methodNotAllowed(Response::Status::methodNotAllowed);
|
||||
methodNotAllowed.replyTo(*request.get());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
std::string path = request->getPath(serverName.value());
|
||||
router.route(path.data(), std::move(request), this);
|
||||
} catch (const std::exception& e) {
|
||||
Response error(Response::Status::internalError);
|
||||
error.setBody(std::string(e.what()));
|
||||
error.replyTo(*request.get());
|
||||
}
|
||||
}
|
||||
|
||||
bool Server::printEnvironment(Request* request, Server* server) {
|
||||
UNUSED(server);
|
||||
nlohmann::json body = nlohmann::json::object();
|
||||
request->printEnvironment(body);
|
||||
|
||||
Response res;
|
||||
res.setBody(body);
|
||||
res.replyTo(*request);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Server::info(Request* request, Server* server) {
|
||||
UNUSED(server);
|
||||
Response res;
|
||||
nlohmann::json body = nlohmann::json::object();
|
||||
body["type"] = PROJECT_NAME;
|
||||
body["version"] = PROJECT_VERSION;
|
||||
|
||||
res.setBody(body);
|
||||
res.replyTo(*request);
|
||||
|
||||
return true;
|
||||
std::string path = request->getPath(serverName.value());
|
||||
router.route(path.data(), std::move(request));
|
||||
}
|
||||
|
|
|
@ -34,9 +34,6 @@ public:
|
|||
private:
|
||||
void handleRequest(std::unique_ptr<Request> request);
|
||||
|
||||
static bool info(Request* request, Server* server);
|
||||
static bool printEnvironment(Request* request, Server* server);
|
||||
|
||||
private:
|
||||
bool terminating;
|
||||
uint64_t requestCount;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue