just some more thoughts
This commit is contained in:
parent
e0a17115f9
commit
86292db6f3
@ -1,12 +1,12 @@
|
|||||||
set(SOURCE_FILES
|
set(SOURCE_FILES
|
||||||
main.cpp
|
main.cpp
|
||||||
server.cpp
|
server.cpp
|
||||||
response.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(HEADER_FILES
|
set(HEADER_FILES
|
||||||
server.h
|
server.h
|
||||||
response.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
target_sources(birdbadge PRIVATE ${SOURCE_FILES})
|
target_sources(birdbadge PRIVATE ${SOURCE_FILES})
|
||||||
|
|
||||||
|
add_subdirectory(response)
|
||||||
|
@ -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<std::string_view> split = splitPath(path);
|
|
||||||
selfIndentification(split);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Response::selfIndentification(const std::vector<std::string_view>& path) {
|
|
||||||
if (path.size() == 0) {
|
|
||||||
status = Status::ok;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Response::writeHeader(std::ostream& out) const {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Response::writeBody(std::ostream& out) const {
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string_view> Response::splitPath(std::string_view path) {
|
|
||||||
std::vector<std::string_view> 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;
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string_view>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
|
|
||||||
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<std::string_view>& path);
|
|
||||||
|
|
||||||
static std::vector<std::string_view> splitPath(std::string_view path);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Status status;
|
|
||||||
std::string body;
|
|
||||||
};
|
|
15
src/response/CMakeLists.txt
Normal file
15
src/response/CMakeLists.txt
Normal file
@ -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})
|
57
src/response/badge.cpp
Normal file
57
src/response/badge.cpp
Normal file
@ -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 << "<rect width=\"100\" height=\"20\" fill=\"#dddddd\" />";
|
||||||
|
out << "<rect x=\"100\" width=\"34\" height=\"20\" fill=\"#0044dd\" />";
|
||||||
|
|
||||||
|
|
||||||
|
out << openBracket << "/" << svgTag << closeBracket;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="134" height="20" role="img" aria-label="Documentation: HTML"><title>Documentation: HTML</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="134" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="93" height="20" fill="#555"/><rect x="93" width="41" height="20" fill="#97ca00"/><rect width="134" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="475" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="830">Documentation</text><text x="475" y="140" transform="scale(.1)" fill="#fff" textLength="830">Documentation</text><text aria-hidden="true" x="1125" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="310">HTML</text><text x="1125" y="140" transform="scale(.1)" fill="#fff" textLength="310">HTML</text></g></svg>
|
||||||
|
|
||||||
|
*/
|
25
src/response/badge.h
Normal file
25
src/response/badge.h
Normal file
@ -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;
|
||||||
|
};
|
17
src/response/notfound.cpp
Normal file
17
src/response/notfound.cpp
Normal file
@ -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;
|
||||||
|
}
|
16
src/response/notfound.h
Normal file
16
src/response/notfound.h
Normal file
@ -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();
|
||||||
|
|
||||||
|
};
|
59
src/response/response.cpp
Normal file
59
src/response/response.cpp
Normal file
@ -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<std::string_view> 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<std::string_view> Response::splitPath(std::string_view path) {
|
||||||
|
std::vector<std::string_view> 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;
|
||||||
|
}
|
41
src/response/response.h
Normal file
41
src/response/response.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
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<std::string_view> 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;
|
||||||
|
};
|
17
src/response/root.cpp
Normal file
17
src/response/root.cpp
Normal file
@ -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;
|
||||||
|
}
|
15
src/response/root.h
Normal file
15
src/response/root.h
Normal file
@ -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();
|
||||||
|
};
|
@ -13,23 +13,12 @@ constexpr static const char* SCRIPT_FILENAME("SCRIPT_FILENAME");
|
|||||||
|
|
||||||
constexpr static const char* SERVER_NAME("SERVER_NAME");
|
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():
|
Server::Server():
|
||||||
requestCount(0),
|
requestCount(0),
|
||||||
serverName(std::nullopt)
|
serverName(std::nullopt)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Server::~Server() {
|
Server::~Server() {}
|
||||||
}
|
|
||||||
|
|
||||||
void Server::handleRequest(FCGX_Request& request) {
|
void Server::handleRequest(FCGX_Request& request) {
|
||||||
accountRequest(request);
|
accountRequest(request);
|
||||||
@ -41,18 +30,23 @@ void Server::handleRequest(FCGX_Request& request) {
|
|||||||
std::ostream errs{&cerr_fcgi_streambuf};
|
std::ostream errs{&cerr_fcgi_streambuf};
|
||||||
std::istream is{&cin_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) {
|
if (requestMethod != GET) {
|
||||||
os << status405;
|
os << Response::status405Header;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeHeader(os);
|
|
||||||
try {
|
try {
|
||||||
std::string_view sPath = getPath(request);
|
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) {
|
} catch (const std::exception e) {
|
||||||
|
writeHeader(os);
|
||||||
os << e.what();
|
os << e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,9 +59,9 @@ void Server::printEnv(std::ostream& out, FCGX_Request& request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Server::writeHeader(std::ostream& out) {
|
void Server::writeHeader(std::ostream& out) {
|
||||||
out << status200 << newLine;
|
out << Response::status200Header << Response::newLine;
|
||||||
out << contentTypeHtml;
|
out << Response::contentTypeHTML;
|
||||||
out << headerEnd;
|
out << Response::headerTerminator;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::accountRequest(const FCGX_Request& request) {
|
void Server::accountRequest(const FCGX_Request& request) {
|
||||||
@ -77,9 +71,7 @@ void Server::accountRequest(const FCGX_Request& request) {
|
|||||||
try {
|
try {
|
||||||
serverName = FCGX_GetParam(SERVER_NAME, request.envp);
|
serverName = FCGX_GetParam(SERVER_NAME, request.envp);
|
||||||
std::cout << "received server name " << serverName.value() << std::endl;
|
std::cout << "received server name " << serverName.value() << std::endl;
|
||||||
} catch (...) {
|
} catch (...) {}
|
||||||
std::cout << "couldn't parse " << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include <fcgiapp.h>
|
#include <fcgiapp.h>
|
||||||
#include <fcgio.h>
|
#include <fcgio.h>
|
||||||
|
|
||||||
#include "response.h"
|
#include "response/response.h"
|
||||||
|
|
||||||
class Server {
|
class Server {
|
||||||
public:
|
public:
|
||||||
@ -25,8 +25,6 @@ private:
|
|||||||
void accountRequest(const FCGX_Request& request);
|
void accountRequest(const FCGX_Request& request);
|
||||||
std::string_view getPath(const FCGX_Request& request);
|
std::string_view getPath(const FCGX_Request& request);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t requestCount;
|
uint64_t requestCount;
|
||||||
std::optional<std::string> serverName;
|
std::optional<std::string> serverName;
|
||||||
|
Loading…
Reference in New Issue
Block a user