рефактор + чистка кода

This commit is contained in:
Vladislav Ostapov 2024-10-30 10:40:38 +03:00
parent 2fef65d9d9
commit 5c348ace87
16 changed files with 47 additions and 130 deletions

View File

@ -27,7 +27,6 @@ add_executable(terminal-web-server
src/server/connection.hpp src/server/connection.hpp
src/server/request_parser.cpp src/server/request_parser.cpp
src/server/server.cpp src/server/server.cpp
src/server/header.hpp
src/server/reply.hpp src/server/reply.hpp
src/server/reply.cpp src/server/reply.cpp
src/server/connection.cpp src/server/connection.cpp

View File

@ -77,12 +77,12 @@ static void initResources(http::server::Server& s) {
s.resources.emplace_back(std::make_unique<http::resource::GenericResource>("/api/statistics", [](const auto& req, auto& rep) { s.resources.emplace_back(std::make_unique<http::resource::GenericResource>("/api/statistics", [](const auto& req, auto& rep) {
if (req.method != "GET") { if (req.method != "GET") {
http::server::stock_reply(http::server::bad_request, rep); http::server::stockReply(http::server::bad_request, rep);
} }
rep.status = http::server::ok; rep.status = http::server::ok;
rep.headers.clear(); rep.headers.clear();
rep.headers.push_back({.name = "Content-Type", .value = to_string(mime_types::json)}); rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::json)});
const char* json = R"({"key":"value"})"; const char* json = R"({"key":"value"})";
rep.content.insert(rep.content.end(), json, json + strlen(json)); rep.content.insert(rep.content.end(), json, json + strlen(json));
})); }));

View File

@ -31,15 +31,15 @@ namespace http::server {
auto self(shared_from_this()); auto self(shared_from_this());
socket_.async_read_some(boost::asio::buffer(buffer_), [this, self](boost::system::error_code ec, std::size_t bytes_transferred) { socket_.async_read_some(boost::asio::buffer(buffer_), [this, self](boost::system::error_code ec, std::size_t bytes_transferred) {
if (!ec) { if (!ec) {
request_parser::result_type result; RequestParser::result_type result;
std::tie(result, std::ignore) = request_parser_.parse( std::tie(result, std::ignore) = request_parser_.parse(
request_, buffer_.data(), buffer_.data() + bytes_transferred); request_, buffer_.data(), buffer_.data() + bytes_transferred);
if (result == request_parser::good) { if (result == RequestParser::good) {
request_handler_(request_, reply_); request_handler_(request_, reply_);
do_write(); do_write();
} else if (result == request_parser::bad) { } else if (result == RequestParser::bad) {
stock_reply(bad_request, reply_); stockReply(bad_request, reply_);
do_write(); do_write();
} else { } else {
do_read(); do_read();
@ -102,15 +102,15 @@ namespace http::server {
auto self(shared_from_this()); auto self(shared_from_this());
stream_.async_read_some(boost::asio::buffer(buffer_), [this, self](boost::system::error_code ec, std::size_t bytes_transferred) { stream_.async_read_some(boost::asio::buffer(buffer_), [this, self](boost::system::error_code ec, std::size_t bytes_transferred) {
if (!ec) { if (!ec) {
request_parser::result_type result; RequestParser::result_type result;
std::tie(result, std::ignore) = request_parser_.parse( std::tie(result, std::ignore) = request_parser_.parse(
request_, buffer_.data(), buffer_.data() + bytes_transferred); request_, buffer_.data(), buffer_.data() + bytes_transferred);
if (result == request_parser::good) { if (result == RequestParser::good) {
request_handler_(request_, reply_); request_handler_(request_, reply_);
doWrite(); doWrite();
} else if (result == request_parser::bad) { } else if (result == RequestParser::bad) {
stock_reply(bad_request, reply_); stockReply(bad_request, reply_);
doWrite(); doWrite();
} else { } else {
doRead(); doRead();

View File

@ -13,7 +13,7 @@
namespace http::server { namespace http::server {
using request_handler = std::function<void(const request &req, reply &rep)>; using request_handler = std::function<void(const Request &req, reply &rep)>;
class ConnectionManager; class ConnectionManager;
/// Represents a single Connection from a client. Base class /// Represents a single Connection from a client. Base class
@ -65,10 +65,10 @@ namespace http::server {
std::array<char, 2048> buffer_{}; std::array<char, 2048> buffer_{};
/// The incoming request. /// The incoming request.
request request_; Request request_;
/// The parser for the incoming request. /// The parser for the incoming request.
request_parser request_parser_; RequestParser request_parser_;
/// The reply to be sent back to the client. /// The reply to be sent back to the client.
reply reply_; reply reply_;
@ -107,10 +107,10 @@ namespace http::server {
std::array<char, 2048> buffer_{}; std::array<char, 2048> buffer_{};
/// The incoming request. /// The incoming request.
request request_; Request request_;
/// The parser for the incoming request. /// The parser for the incoming request.
request_parser request_parser_; RequestParser request_parser_;
/// The reply to be sent back to the client. /// The reply to be sent back to the client.
reply reply_; reply reply_;

View File

@ -1,13 +1,3 @@
//
// header.hpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef HTTP_HEADER_HPP #ifndef HTTP_HEADER_HPP
#define HTTP_HEADER_HPP #define HTTP_HEADER_HPP

View File

@ -1,13 +1,3 @@
//
// mime_types.cpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "mime_types.hpp" #include "mime_types.hpp"
@ -24,7 +14,7 @@ namespace http::server::mime_types {
{"png", "image/png"} {"png", "image/png"}
}; };
std::string extension_to_type(const std::string &extension) { std::string extensionToType(const std::string &extension) {
for (mapping m: mappings) { for (mapping m: mappings) {
if (m.extension == extension) { if (m.extension == extension) {
return m.mime_type; return m.mime_type;
@ -35,7 +25,7 @@ namespace http::server::mime_types {
} }
} // namespace http::server::mime_types } // namespace http::server::mime_types
std::string http::server::mime_types::to_string(Mime m) { std::string http::server::mime_types::toString(Mime m) {
switch (m) { switch (m) {
case image_gif: return "image/gif"; case image_gif: return "image/gif";
case image_png: return "image/png"; case image_png: return "image/png";

View File

@ -1,13 +1,3 @@
//
// mime_types.hpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef HTTP_MIME_TYPES_HPP #ifndef HTTP_MIME_TYPES_HPP
#define HTTP_MIME_TYPES_HPP #define HTTP_MIME_TYPES_HPP
@ -30,10 +20,10 @@ namespace http::server::mime_types {
blob // application/octet-stream blob // application/octet-stream
}; };
std::string to_string(Mime m); std::string toString(Mime m);
/// Convert a file extension into a MIME type. /// Convert a file extension into a MIME type.
std::string extension_to_type(const std::string &extension); std::string extensionToType(const std::string &extension);
} // namespace http::Server::mime_types } // namespace http::Server::mime_types

View File

@ -1,13 +1,3 @@
//
// reply.cpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "reply.hpp" #include "reply.hpp"
#include <string> #include <string>
@ -216,10 +206,10 @@ namespace http::server {
} }
} // namespace stock_replies } // namespace stock_replies
void stock_reply(status_type status, reply& rep) { void stockReply(status_type status, reply& rep) {
rep.status = status; rep.status = status;
rep.headers.clear(); rep.headers.clear();
rep.headers.push_back({.name = "Content-Type", .value = to_string(mime_types::text_html)}); rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::text_html)});
stock_replies::as_content(status, rep.content); stock_replies::as_content(status, rep.content);
} }
} // namespace http::server } // namespace http::server

View File

@ -1,17 +1,6 @@
//
// reply.hpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef HTTP_REPLY_HPP #ifndef HTTP_REPLY_HPP
#define HTTP_REPLY_HPP #define HTTP_REPLY_HPP
#include <string>
#include <vector> #include <vector>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "header.hpp" #include "header.hpp"
@ -55,7 +44,7 @@ namespace http::server {
}; };
/// Get a stock reply. /// Get a stock reply.
void stock_reply(status_type status, reply& rep); void stockReply(status_type status, reply& rep);
} // namespace http::Server } // namespace http::Server

View File

@ -1,13 +1,3 @@
//
// request.hpp
// ~~~~~~~~~~~
//
// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef HTTP_REQUEST_HPP #ifndef HTTP_REQUEST_HPP
#define HTTP_REQUEST_HPP #define HTTP_REQUEST_HPP
@ -18,7 +8,7 @@
namespace http::server { namespace http::server {
/// A request received from a client. /// A request received from a client.
struct request { struct Request {
std::string method; std::string method;
std::string uri; std::string uri;
bool is_keep_alive; bool is_keep_alive;

View File

@ -1,27 +1,17 @@
//
// request_parser.cpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "request_parser.hpp" #include "request_parser.hpp"
#include "request.hpp" #include "request.hpp"
namespace http::server { namespace http::server {
request_parser::request_parser() RequestParser::RequestParser()
: state_(method_start) { : state_(method_start) {
} }
void request_parser::reset() { void RequestParser::reset() {
state_ = method_start; state_ = method_start;
} }
request_parser::result_type request_parser::consume(request &req, char input) { RequestParser::result_type RequestParser::consume(Request &req, char input) {
switch (state_) { switch (state_) {
case method_start: case method_start:
if (!is_char(input) || is_ctl(input) || is_tspecial(input)) { if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
@ -200,15 +190,15 @@ namespace http::server {
} }
} }
bool request_parser::is_char(int c) { bool RequestParser::is_char(int c) {
return c >= 0 && c <= 127; return c >= 0 && c <= 127;
} }
bool request_parser::is_ctl(int c) { bool RequestParser::is_ctl(int c) {
return (c >= 0 && c <= 31) || (c == 127); return (c >= 0 && c <= 31) || (c == 127);
} }
bool request_parser::is_tspecial(int c) { bool RequestParser::is_tspecial(int c) {
switch (c) { switch (c) {
case '(': case '(':
case ')': case ')':
@ -235,7 +225,7 @@ namespace http::server {
} }
} }
bool request_parser::is_digit(int c) { bool RequestParser::is_digit(int c) {
return c >= '0' && c <= '9'; return c >= '0' && c <= '9';
} }
} // namespace http::server } // namespace http::server

View File

@ -1,13 +1,3 @@
//
// request_parser.hpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef HTTP_REQUEST_PARSER_HPP #ifndef HTTP_REQUEST_PARSER_HPP
#define HTTP_REQUEST_PARSER_HPP #define HTTP_REQUEST_PARSER_HPP
@ -18,13 +8,13 @@
namespace http::server { namespace http::server {
struct request; struct Request;
/// Parser for incoming requests. /// Parser for incoming requests.
class request_parser { class RequestParser {
public: public:
/// Construct ready to parse the request method. /// Construct ready to parse the request method.
request_parser(); RequestParser();
/// Reset to initial parser state. /// Reset to initial parser state.
void reset(); void reset();
@ -37,7 +27,7 @@ namespace http::server {
/// required. The InputIterator return value indicates how much of the input /// required. The InputIterator return value indicates how much of the input
/// has been consumed. /// has been consumed.
template<typename InputIterator> template<typename InputIterator>
std::tuple<result_type, InputIterator> parse(request &req, InputIterator begin, InputIterator end) { std::tuple<result_type, InputIterator> parse(Request &req, InputIterator begin, InputIterator end) {
while (begin != end) { while (begin != end) {
result_type result = consume(req, *begin++); result_type result = consume(req, *begin++);
if (result == good || result == bad) if (result == good || result == bad)
@ -48,7 +38,7 @@ namespace http::server {
private: private:
/// Handle the next character of input. /// Handle the next character of input.
result_type consume(request &req, char input); result_type consume(Request &req, char input);
/// Check if a byte is an HTTP character. /// Check if a byte is an HTTP character.
static bool is_char(int c); static bool is_char(int c);

View File

@ -1,6 +1,5 @@
#include "resource.h" #include "resource.h"
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <boost/asio/buffer.hpp>
#include <fstream> #include <fstream>
static void loadFile(const std::string& path, std::vector<char>& content) { static void loadFile(const std::string& path, std::vector<char>& content) {
@ -31,9 +30,9 @@ http::resource::StaticFileResource::StaticFileResource(const std::string &path,
#endif #endif
} }
void http::resource::StaticFileResource::handle(const server::request &req, server::reply &rep) { void http::resource::StaticFileResource::handle(const server::Request &req, server::reply &rep) {
if (req.method != "GET") { if (req.method != "GET") {
stock_reply(server::bad_request, rep); stockReply(server::bad_request, rep);
return; return;
} }
@ -48,7 +47,7 @@ void http::resource::StaticFileResource::handle(const server::request &req, serv
rep.status = server::ok; rep.status = server::ok;
rep.headers.clear(); rep.headers.clear();
// TODO сделать cache control // TODO сделать cache control
rep.headers.push_back({.name = "Content-Type", .value = to_string(this->type)}); rep.headers.push_back({.name = "Content-Type", .value = toString(this->type)});
} }
http::resource::StaticFileResource::~StaticFileResource() = default; http::resource::StaticFileResource::~StaticFileResource() = default;
@ -57,7 +56,7 @@ http::resource::GenericResource::GenericResource(const std::string &path, const
this->path = path; this->path = path;
} }
void http::resource::GenericResource::handle(const server::request &req, server::reply &rep) { void http::resource::GenericResource::handle(const server::Request &req, server::reply &rep) {
this->generator_(req, rep); this->generator_(req, rep);
} }

View File

@ -14,7 +14,7 @@ namespace http::resource {
public: public:
std::string path; std::string path;
virtual void handle(const server::request &req, server::reply &rep) = 0; virtual void handle(const server::Request &req, server::reply &rep) = 0;
virtual ~BasicResource() = default; virtual ~BasicResource() = default;
}; };
@ -34,12 +34,12 @@ namespace http::resource {
public: public:
StaticFileResource(const std::string& path, const std::string& filePath, server::mime_types::Mime type); StaticFileResource(const std::string& path, const std::string& filePath, server::mime_types::Mime type);
void handle(const server::request &req, server::reply &rep) override; void handle(const server::Request &req, server::reply &rep) override;
~StaticFileResource() override; ~StaticFileResource() override;
}; };
using respGenerator = std::function<void(const server::request &req, server::reply &rep)>; using respGenerator = std::function<void(const server::Request &req, server::reply &rep)>;
/** /**
* Класс ресурса для POST-запросов * Класс ресурса для POST-запросов
@ -51,7 +51,7 @@ namespace http::resource {
public: public:
GenericResource(const std::string& path, const respGenerator& generator); GenericResource(const std::string& path, const respGenerator& generator);
void handle(const server::request &req, server::reply &rep) override; void handle(const server::Request &req, server::reply &rep) override;
~GenericResource() override; ~GenericResource() override;
}; };

View File

@ -112,14 +112,14 @@ namespace http::server {
}); });
} }
void Server::requestHandler(const request &req, reply &rep) { void Server::requestHandler(const Request &req, reply &rep) {
boost::urls::url_view url(req.uri); boost::urls::url_view url(req.uri);
const auto path = url.path(); const auto path = url.path();
// Request path must be absolute and not contain "..". // Request path must be absolute and not contain "..".
if (path.empty() || path[0] != '/' || path.find("..") != std::string::npos) { if (path.empty() || path[0] != '/' || path.find("..") != std::string::npos) {
stock_reply(bad_request, rep); stockReply(bad_request, rep);
return; return;
} }
@ -135,7 +135,7 @@ namespace http::server {
return; return;
} }
stock_reply(not_found, rep); stockReply(not_found, rep);
} }
} // namespace http::Server } // namespace http::Server

View File

@ -74,7 +74,7 @@ namespace http::server {
ConnectionManager connection_manager_; ConnectionManager connection_manager_;
/// Handle a request and produce a reply. /// Handle a request and produce a reply.
void requestHandler(const request &req, reply &rep); void requestHandler(const Request &req, reply &rep);
}; };
} // namespace http::Server } // namespace http::Server