first couple of requests

This commit is contained in:
Blue 2023-11-23 16:57:32 -03:00
parent 68e795f0e6
commit aae7873d67
Signed by: blue
GPG key ID: 9B203B252A63EE38
11 changed files with 152 additions and 34 deletions

View file

@ -1,9 +1,11 @@
set(HEADERS
server.h
router.h
)
set(SOURCES
server.cpp
router.cpp
)
target_sources(pica PRIVATE ${SOURCES})

41
server/router.cpp Normal file
View file

@ -0,0 +1,41 @@
#include "router.h"
Router::Router():
table()
{
}
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";
}
void Router::route(const std::string& path, std::unique_ptr<Request> request) {
auto itr = table.find(path);
if (itr == table.end())
return handleNotFound(path, std::move(request));
try {
bool result = itr->second(request.get());
if (!result)
handleInternalError(std::runtime_error("handler failed to handle the request"), std::move(request));
} catch (const std::exception& e) {
handleInternalError(e, std::move(request));
}
}
void Router::handleNotFound(const std::string& path, std::unique_ptr<Request> request) {
Response notFound(Response::Status::notFound);
notFound.setBody(std::string("Path \"") + path + "\" was not found");
notFound.replyTo(*request.get());
std::cerr << "Not found: " << path << std::endl;
}
void Router::handleInternalError(const std::exception& exception, std::unique_ptr<Request> request) {
Response error(Response::Status::internalError);
error.setBody(std::string(exception.what()));
error.replyTo(*request.get());
std::cerr << "Internal error: " << exception.what() << std::endl;
}

27
server/router.h Normal file
View file

@ -0,0 +1,27 @@
#pragma once
#include <map>
#include <functional>
#include <string>
#include <memory>
#include "request/request.h"
#include "response/response.h"
class Router {
public:
using Handler = std::function<bool(Request*)>;
Router();
void addRoute(const std::string& path, const 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);
private:
std::map<std::string, Handler> table;
};

View file

@ -8,14 +8,15 @@ constexpr static const char* DOCUMENT_ROOT("DOCUMENT_ROOT");
constexpr static const char* SCRIPT_NAME("SCRIPT_NAME");
constexpr static const char* SCRIPT_FILENAME("SCRIPT_FILENAME");
constexpr std::string_view info("info");
constexpr std::string_view env("env");
Server::Server():
terminating(false),
requestCount(0),
serverName(std::nullopt)
{}
serverName(std::nullopt),
router()
{
router.addRoute("info", Server::info);
router.addRoute("env", Server::printEnvironment);
}
Server::~Server() {}
@ -52,27 +53,34 @@ void Server::handleRequest(std::unique_ptr<Request> request) {
}
try {
std::string_view sPath = request->getPath(serverName.value());
if (sPath == info) {
Response res;
res.setBody("Pica<br>\nVersion: 1.0.0<br>\nRequestsHandled: " + std::to_string(requestCount));
res.replyTo(*request.get());
} else if (sPath == env) {
std::ostringstream ss;
request->printEnvironment(ss);
Response res;
res.setBody(ss.str());
res.replyTo(*request.get());
} else {
Response notFound(Response::Status::notFound);
notFound.setBody(std::string("Path ") + sPath.data() + " was not found");
notFound.replyTo(*request.get());
std::cerr << "Not found: " << sPath.data() << std::endl;
}
std::string path = request->getPath(serverName.value());
router.route(path.data(), std::move(request));
} catch (const std::exception e) {
Response error(Response::Status::internalError);
error.setBody(e.what());
error.setBody(std::string(e.what()));
error.replyTo(*request.get());
}
}
bool Server::printEnvironment(Request* request) {
nlohmann::json body = nlohmann::json::object();
request->printEnvironment(body);
Response res;
res.setBody(body);
res.replyTo(*request);
return true;
}
bool Server::info(Request* request) {
Response res;
nlohmann::json body = nlohmann::json::object();
body["type"] = "Pica";
body["version"] = "0.0.1";
res.setBody(body);
res.replyTo(*request);
return true;
}

View file

@ -12,8 +12,11 @@
#include <fcgio.h>
#include <stdint.h>
#include <nlohmann/json.hpp>
#include "request/request.h"
#include "response/response.h"
#include "router.h"
class Server {
public:
@ -24,12 +27,13 @@ public:
private:
void handleRequest(std::unique_ptr<Request> request);
void router(const std::vector<std::string_view>& path);
void printEnv(std::ostream& out, FCGX_Request& request);
std::string_view getPath(const FCGX_Request& request);
static bool info(Request* request);
static bool printEnvironment(Request* request);
private:
bool terminating;
uint64_t requestCount;
std::optional<std::string> serverName;
Router router;
};