From 86292db6f36a0c9bc14a89080372f716bc8bc609 Mon Sep 17 00:00:00 2001 From: blue Date: Tue, 18 Apr 2023 13:16:36 -0300 Subject: [PATCH] just some more thoughts --- src/CMakeLists.txt | 4 +-- src/response.cpp | 42 -------------------------- src/response.h | 28 ------------------ src/response/CMakeLists.txt | 15 ++++++++++ src/response/badge.cpp | 57 +++++++++++++++++++++++++++++++++++ src/response/badge.h | 25 ++++++++++++++++ src/response/notfound.cpp | 17 +++++++++++ src/response/notfound.h | 16 ++++++++++ src/response/response.cpp | 59 +++++++++++++++++++++++++++++++++++++ src/response/response.h | 41 ++++++++++++++++++++++++++ src/response/root.cpp | 17 +++++++++++ src/response/root.h | 15 ++++++++++ src/server.cpp | 36 +++++++++------------- src/server.h | 4 +-- 14 files changed, 279 insertions(+), 97 deletions(-) delete mode 100644 src/response.cpp delete mode 100644 src/response.h create mode 100644 src/response/CMakeLists.txt create mode 100644 src/response/badge.cpp create mode 100644 src/response/badge.h create mode 100644 src/response/notfound.cpp create mode 100644 src/response/notfound.h create mode 100644 src/response/response.cpp create mode 100644 src/response/response.h create mode 100644 src/response/root.cpp create mode 100644 src/response/root.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index da0cd06..1d3d7dc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,12 +1,12 @@ set(SOURCE_FILES main.cpp server.cpp - response.cpp ) set(HEADER_FILES server.h - response.h ) target_sources(birdbadge PRIVATE ${SOURCE_FILES}) + +add_subdirectory(response) diff --git a/src/response.cpp b/src/response.cpp deleted file mode 100644 index 146fe53..0000000 --- a/src/response.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "response.h" - -constexpr static const char* pathDelimiter("/"); - -Response::Response(const std::string_view& path): - status(Status::ok), - body() -{ - std::vector split = splitPath(path); - selfIndentification(split); -} - -void Response::selfIndentification(const std::vector& path) { - if (path.size() == 0) { - status = Status::ok; - } -} - -void Response::writeHeader(std::ostream& out) const { -} - -void Response::writeBody(std::ostream& out) const { -} - -std::vector Response::splitPath(std::string_view path) { - std::vector output; - std::string_view::size_type first = 0; - - while (first < path.size()) { - const std::string_view::size_type second = path.find_first_of(pathDelimiter, first); - - if (first != second) - output.emplace_back(path.substr(first, second - first)); - - if (second == std::string_view::npos) - break; - - first = second + 1; - } - - return output; -} diff --git a/src/response.h b/src/response.h deleted file mode 100644 index 61acf1f..0000000 --- a/src/response.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include -#include - - -class Response { -public: - enum Status { - ok, - notFound, - error - }; - - Response(const std::string_view& path); - - void writeHeader(std::ostream& out) const; - void writeBody(std::ostream& out) const; - -private: - void selfIndentification(const std::vector& path); - - static std::vector splitPath(std::string_view path); - -private: - Status status; - std::string body; -}; diff --git a/src/response/CMakeLists.txt b/src/response/CMakeLists.txt new file mode 100644 index 0000000..5b887d8 --- /dev/null +++ b/src/response/CMakeLists.txt @@ -0,0 +1,15 @@ +set(SOURCE_FILES + response.cpp + root.cpp + notfound.cpp + badge.cpp +) + +set(HEADER_FILES + response.h + root.h + notfound.h + badge.h +) + +target_sources(birdbadge PRIVATE ${SOURCE_FILES}) diff --git a/src/response/badge.cpp b/src/response/badge.cpp new file mode 100644 index 0000000..576c66d --- /dev/null +++ b/src/response/badge.cpp @@ -0,0 +1,57 @@ +#include "badge.h" + +constexpr const char* openBracket("<"); +constexpr const char* closeBracket(">"); +constexpr const char* svgTag("svg"); +constexpr const char* titleTag("title"); + +constexpr const char* svgAttrs = + "xmlns=\"http://www.w3.org/2000/svg\" " + "xmlns:xlink=\"http://www.w3.org/1999/xlink\" " + "width=\"134\" " + "height=\"20\" " + "role=\"img\""; +constexpr const char* ariaLabel("aria-label"); + +Badge::Badge(Badge::Kind kind, const std::string& title, const std::string& value, const std::string& color): + Response(Type::image), + kind(kind), + title(title), + value(value), + color(color) +{} + +Badge::~Badge() {} + +void Badge::writeHeader(std::ostream& out) const { + out << status200Header << newLine; + out << contentTypeSVG; + out << headerTerminator; +} + +void Badge::writeBody(std::ostream& out) const { + out << openBracket << svgTag << " "; + out << svgAttrs << " "; + out << ariaLabel << "=\"" << title << ": " << value << "\""; + out << closeBracket; + + out << openBracket << titleTag << closeBracket; + out << title << ": " << value; + out << openBracket << "/" << titleTag << closeBracket; + + //may be gradients + //may be round corners + + out << ""; + out << ""; + + + out << openBracket << "/" << svgTag << closeBracket; +} + + +/** + +Documentation: HTMLDocumentationHTML + +*/ diff --git a/src/response/badge.h b/src/response/badge.h new file mode 100644 index 0000000..6294b2d --- /dev/null +++ b/src/response/badge.h @@ -0,0 +1,25 @@ +#pragma once + +#include "response.h" + +class Badge: public Response { + friend class Response; +public: + enum class Kind { + allStatic + }; + + ~Badge() override; + + void writeBody(std::ostream & out) const override; + void writeHeader(std::ostream & out) const override; + +protected: + Badge(Kind kind, const std::string& title = "", const std::string& value = "", const std::string& color = ""); + +protected: + Kind kind; + std::string title; + std::string value; + std::string color; +}; diff --git a/src/response/notfound.cpp b/src/response/notfound.cpp new file mode 100644 index 0000000..1aeea8a --- /dev/null +++ b/src/response/notfound.cpp @@ -0,0 +1,17 @@ +#include "notfound.h" + +NotFound::NotFound(): + Response(Type::error) +{} + +NotFound::~NotFound() {} + +void NotFound::writeHeader(std::ostream& out) const { + out << status404Header << newLine; + out << contentTypeHTML << newLine; + out << headerTerminator; +} + +void NotFound::writeBody(std::ostream& out) const { + out << "Page you're requesting was not found" << newLine; +} diff --git a/src/response/notfound.h b/src/response/notfound.h new file mode 100644 index 0000000..682a972 --- /dev/null +++ b/src/response/notfound.h @@ -0,0 +1,16 @@ +#pragma once + +#include "response.h" + +class NotFound: public Response { + friend class Response; +public: + ~NotFound() override; + + void writeHeader(std::ostream & out) const override; + void writeBody(std::ostream & out) const override; + +protected: + NotFound(); + +}; diff --git a/src/response/response.cpp b/src/response/response.cpp new file mode 100644 index 0000000..95cbfbc --- /dev/null +++ b/src/response/response.cpp @@ -0,0 +1,59 @@ +#include "response.h" + +#include "root.h" +#include "notfound.h" +#include "badge.h" + +const char* Response::status200Header("Status: 200 OK"); +const char* Response::status404Header("Status: 404 Not Found"); +const char* Response::status405Header("Status: 405 Method Not Allowed"); +const char* Response::status500Header("Status: 500 Internal Error"); + +const char* Response::pathDelimiter("/"); +const char* Response::newLine("\n"); +const char* Response::headerTerminator("\n\n"); + +const char* Response::contentTypeHTML("Content-type: text/html"); +const char* Response::contentTypeSVG("Content-type: image/svg+xml;charset=utf-8"); + +constexpr const char* staticHop("static"); + +Response::Response(Type type): + type(type) +{} + +Response::~Response() {} + +Response* Response::create(const std::string_view& path) { + std::vector split = splitPath(path); + + if (path.size() == 0) { + return new Root(); + } + + const std::string_view& firstHop = split[0]; + if (firstHop == staticHop) { + return new Badge(Badge::Kind::allStatic); + } + + return new NotFound(); +} + +std::vector Response::splitPath(std::string_view path) { + std::vector output; + std::string_view::size_type first = 0; + + while (first < path.size()) { + const std::string_view::size_type second = path.find_first_of(pathDelimiter, first); + + if (first != second) + output.emplace_back(path.substr(first, second - first)); + + if (second == std::string_view::npos) + break; + + first = second + 1; + } + + return output; +} diff --git a/src/response/response.h b/src/response/response.h new file mode 100644 index 0000000..ce437c2 --- /dev/null +++ b/src/response/response.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include +#include + +class Response { +public: + enum Type { + image, + root, + error + }; + + virtual ~Response(); + virtual void writeHeader(std::ostream& out) const = 0; + virtual void writeBody(std::ostream& out) const = 0; + + static Response* create(const std::string_view& path); + +protected: + Response(Type type); + + static std::vector splitPath(std::string_view path); + +public: + const Type type; + + static const char* status200Header; + static const char* status404Header; + static const char* status405Header; + static const char* status500Header; + + static const char* pathDelimiter; + static const char* newLine; + static const char* headerTerminator; + + static const char* contentTypeHTML; + static const char* contentTypeSVG; +}; diff --git a/src/response/root.cpp b/src/response/root.cpp new file mode 100644 index 0000000..2941e85 --- /dev/null +++ b/src/response/root.cpp @@ -0,0 +1,17 @@ +#include "root.h" + +Root::Root(): + Response(Type::root) +{} + +Root::~Root() {} + +void Root::writeHeader(std::ostream& out) const { + out << status200Header << newLine; + out << contentTypeHTML << newLine; + out << headerTerminator; +} + +void Root::writeBody(std::ostream& out) const { + out << "Hello! This is Birdbadge root page!" << newLine; +} diff --git a/src/response/root.h b/src/response/root.h new file mode 100644 index 0000000..b2ca329 --- /dev/null +++ b/src/response/root.h @@ -0,0 +1,15 @@ +#pragma once + +#include "response.h" + +class Root: public Response { + friend class Response; +public: + ~Root() override; + + void writeBody(std::ostream & out) const override; + void writeHeader(std::ostream & out) const override; + +protected: + Root(); +}; diff --git a/src/server.cpp b/src/server.cpp index e34dbef..a29052c 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -13,23 +13,12 @@ constexpr static const char* SCRIPT_FILENAME("SCRIPT_FILENAME"); constexpr static const char* SERVER_NAME("SERVER_NAME"); -constexpr static const char* status405("Status: 405 Method Not Allowed"); -constexpr static const char* status500("Status: 500 Internal Error"); -constexpr static const char* status200("Status: 200 OK"); -constexpr static const char* contentTypeHtml("Content-type: text/html"); - -constexpr static const char* headerEnd("\n\n"); -constexpr static const char* newLine("\n"); - -constexpr static const char* svgHeader("image/svg+xml;charset=utf-8"); - Server::Server(): requestCount(0), serverName(std::nullopt) {} -Server::~Server() { -} +Server::~Server() {} void Server::handleRequest(FCGX_Request& request) { accountRequest(request); @@ -41,18 +30,23 @@ void Server::handleRequest(FCGX_Request& request) { std::ostream errs{&cerr_fcgi_streambuf}; std::istream is{&cin_fcgi_streambuf}; - std::string requestMethod(FCGX_GetParam(REQUEST_METHOD, request.envp)); + std::string_view requestMethod(FCGX_GetParam(REQUEST_METHOD, request.envp)); if (requestMethod != GET) { - os << status405; + os << Response::status405Header; return; } - writeHeader(os); try { std::string_view sPath = getPath(request); - Response response(sPath); + Response* response = Response::create(sPath); + + response->writeHeader(os); + response->writeBody(os); + + delete response; } catch (const std::exception e) { + writeHeader(os); os << e.what(); } } @@ -65,9 +59,9 @@ void Server::printEnv(std::ostream& out, FCGX_Request& request) { } void Server::writeHeader(std::ostream& out) { - out << status200 << newLine; - out << contentTypeHtml; - out << headerEnd; + out << Response::status200Header << Response::newLine; + out << Response::contentTypeHTML; + out << Response::headerTerminator; } void Server::accountRequest(const FCGX_Request& request) { @@ -77,9 +71,7 @@ void Server::accountRequest(const FCGX_Request& request) { try { serverName = FCGX_GetParam(SERVER_NAME, request.envp); std::cout << "received server name " << serverName.value() << std::endl; - } catch (...) { - std::cout << "couldn't parse " << std::endl; - } + } catch (...) {} } } diff --git a/src/server.h b/src/server.h index 3540b45..01508da 100644 --- a/src/server.h +++ b/src/server.h @@ -9,7 +9,7 @@ #include #include -#include "response.h" +#include "response/response.h" class Server { public: @@ -25,8 +25,6 @@ private: void accountRequest(const FCGX_Request& request); std::string_view getPath(const FCGX_Request& request); - - private: uint64_t requestCount; std::optional serverName;