// SPDX-FileCopyrightText: 2023 Yury Gubich // SPDX-License-Identifier: GPL-3.0-or-later #include "router.h" Router::Router(): get(), post() {} void Router::addRoute(Handler handler) { std::pair::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)); } if (!result.second) 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) { std::map::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 { std::cout << "Handling " << path << "..." << std::endl; 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(path, e, std::move(request)); } } void Router::handleNotFound(const std::string& path, std::unique_ptr request) { Response notFound(*request.get(), Response::Status::notFound); notFound.setBody(std::string("Path \"") + path + "\" was not found"); notFound.send(); std::cerr << "Not found:\t" << path << std::endl; } void Router::handleInternalError(const std::string& path, const std::exception& exception, std::unique_ptr request) { Response error(*request.get(), Response::Status::internalError); error.setBody(std::string(exception.what())); 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) { 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; }