HTTP -> Http
This commit is contained in:
parent
0d77aa7e3c
commit
61a7e85e52
10 changed files with 55 additions and 55 deletions
|
@ -2,15 +2,15 @@
|
|||
#include <cserver/engine/basic/task_processor.hpp>
|
||||
#include <cserver/server/handlers/http_handler_base.hpp>
|
||||
|
||||
struct SomeComponent : public cserver::server::handlers::HTTPHandlerBaseWithAdder<SomeComponent> {
|
||||
struct SomeComponent : public cserver::server::handlers::HttpHandlerBaseWithAdder<SomeComponent> {
|
||||
static constexpr utempl::ConstexprString kPath = "/v1/some/";
|
||||
static constexpr utempl::ConstexprString kName = "name";
|
||||
static constexpr utempl::ConstexprString kHandlerManagerName = "server";
|
||||
inline constexpr SomeComponent(auto name, auto& context) :
|
||||
HTTPHandlerBaseWithAdder(name, context) {};
|
||||
HttpHandlerBaseWithAdder(name, context) {};
|
||||
|
||||
inline auto HandleRequestThrow(const cserver::server::http::HTTPRequest& request) -> cserver::Task<cserver::server::http::HTTPResponse> {
|
||||
co_return cserver::server::http::HTTPResponse{.body = request.url.data()};
|
||||
inline auto HandleRequestThrow(const cserver::server::http::HttpRequest& request) -> cserver::Task<cserver::server::http::HttpResponse> {
|
||||
co_return cserver::server::http::HttpResponse{.body = request.url.data()};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -52,16 +52,16 @@ private:
|
|||
std::unreachable();
|
||||
}();
|
||||
} else {
|
||||
return [] -> server::http::HTTPResponse {
|
||||
return [] -> server::http::HttpResponse {
|
||||
std::unreachable();
|
||||
}();
|
||||
};
|
||||
};
|
||||
template <typename Socket>
|
||||
inline auto ReadHeaders(Socket&& socket, auto&&...) const -> cserver::Task<server::http::HTTPResponse> {
|
||||
inline auto ReadHeaders(Socket&& socket, auto&&...) const -> cserver::Task<server::http::HttpResponse> {
|
||||
std::string serverResponse;
|
||||
co_await boost::asio::async_read_until(socket, boost::asio::dynamic_buffer(serverResponse), "\r\n\r\n", boost::asio::use_awaitable);
|
||||
server::http::HTTPResponse response;
|
||||
server::http::HttpResponse response;
|
||||
std::istringstream responseStream(std::move(serverResponse));
|
||||
std::string httpVersion;
|
||||
responseStream >> httpVersion >> response.statusCode;
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace cserver::clients::http {
|
|||
template <typename HttpClient>
|
||||
struct Request {
|
||||
HttpClient& client;
|
||||
server::http::HTTPRequest request;
|
||||
server::http::HttpRequest request;
|
||||
Request(HttpClient& client) :
|
||||
client(client) {
|
||||
this->AddHeader("User-Agent", "cserver/1");
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
namespace cserver::clients::http {
|
||||
|
||||
template <typename HttpClient, typename Socket>
|
||||
class Response : public server::http::HTTPResponse {
|
||||
class Response : public server::http::HttpResponse {
|
||||
HttpClient& client;
|
||||
Socket socket;
|
||||
|
||||
|
@ -25,10 +25,10 @@ public:
|
|||
};
|
||||
inline constexpr Response(Response&&) = default;
|
||||
inline constexpr Response(const Response&) = default;
|
||||
inline constexpr Response(HttpClient& client, Socket socket, server::http::HTTPResponse response) :
|
||||
inline constexpr Response(HttpClient& client, Socket socket, server::http::HttpResponse response) :
|
||||
client(client),
|
||||
socket(std::move(socket)),
|
||||
HTTPResponse(std::move(response)) {};
|
||||
HttpResponse(std::move(response)) {};
|
||||
};
|
||||
|
||||
} // namespace cserver::clients::http
|
||||
|
|
|
@ -7,16 +7,16 @@
|
|||
|
||||
namespace cserver::server::handlers {
|
||||
|
||||
struct HTTPHandlerBase {
|
||||
struct HttpHandlerBase {
|
||||
template <typename T, utempl::ConstexprString name, Options Options>
|
||||
static consteval auto Adder(const auto& context) {
|
||||
static consteval auto HttpHandlerAdder(const auto& context) {
|
||||
return context.TransformComponents([]<typename TT>(const ComponentConfig<T::kHandlerManagerName, TT, Options>) {
|
||||
return ComponentConfig<T::kHandlerManagerName, typename TT::template AddHandler<ComponentConfig<name, T, Options>>, Options>{};
|
||||
});
|
||||
};
|
||||
template <typename Self>
|
||||
inline auto HandleRequest(this Self&& self, http::HTTPRequest&& request
|
||||
) -> Task<http::HTTPResponse> requires requires{self.HandleRequestThrow(std::move(request));} {
|
||||
inline auto HandleRequest(this Self&& self, http::HttpRequest&& request
|
||||
) -> Task<http::HttpResponse> requires requires{self.HandleRequestThrow(std::move(request));} {
|
||||
using T = std::remove_cvref_t<Self>;
|
||||
try {
|
||||
co_return co_await std::forward<Self>(self).HandleRequestThrow(std::move(request));
|
||||
|
@ -25,11 +25,11 @@ struct HTTPHandlerBase {
|
|||
} catch(...) {
|
||||
fmt::println("Error in handler with default name {}: Unknown Error", T::kName);
|
||||
};
|
||||
co_return http::HTTPResponse{.statusCode = 500, .statusMessage = "Internal Server Error", .body = "Internal Server Error"};
|
||||
co_return http::HttpResponse{.statusCode = 500, .statusMessage = "Internal Server Error", .body = "Internal Server Error"};
|
||||
};
|
||||
template <typename Self>
|
||||
inline auto HandleRequestStream(this Self&& self, cserver::server::http::HTTPRequest&& request,
|
||||
cserver::server::http::HTTPStream& stream) -> Task<void> requires requires{self.HandleRequestStreamThrow(std::move(request), stream);} {
|
||||
inline auto HandleRequestStream(this Self&& self, cserver::server::http::HttpRequest&& request,
|
||||
cserver::server::http::HttpStream& stream) -> Task<void> requires requires{self.HandleRequestStreamThrow(std::move(request), stream);} {
|
||||
using T = std::remove_cvref_t<Self>;
|
||||
try {
|
||||
co_await std::forward<Self>(self).HandleRequestStreamThrow(std::move(request), stream);
|
||||
|
@ -40,20 +40,20 @@ struct HTTPHandlerBase {
|
|||
};
|
||||
co_await stream.Close();
|
||||
};
|
||||
inline constexpr HTTPHandlerBase(auto, auto&) {};
|
||||
inline constexpr HttpHandlerBase(auto, auto&) {};
|
||||
};
|
||||
template <typename T>
|
||||
struct HTTPHandlerAdder {
|
||||
struct HttpHandlerAdderType {
|
||||
template <utempl::ConstexprString Name, Options Options>
|
||||
static consteval auto Adder(const auto& context) {
|
||||
return HTTPHandlerBase::template Adder<T, Name, Options>(context);
|
||||
return HttpHandlerBase::template HttpHandlerAdder<T, Name, Options>(context);
|
||||
};
|
||||
};
|
||||
template <typename T>
|
||||
struct HTTPHandlerBaseWithAdder : HTTPHandlerBase, HTTPHandlerAdder<T> {
|
||||
inline constexpr HTTPHandlerBaseWithAdder(auto name, auto& context) :
|
||||
HTTPHandlerBase(name, context),
|
||||
HTTPHandlerAdder<T>{} {};
|
||||
struct HttpHandlerBaseWithAdder : HttpHandlerBase, HttpHandlerAdderType<T> {
|
||||
inline constexpr HttpHandlerBaseWithAdder(auto name, auto& context) :
|
||||
HttpHandlerBase(name, context),
|
||||
HttpHandlerAdderType<T>{} {};
|
||||
};
|
||||
|
||||
} // namespace cserver::server::handlers
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
|
||||
namespace cserver::server::http {
|
||||
|
||||
struct HTTPRequest {
|
||||
struct HttpRequest {
|
||||
std::string method = {};
|
||||
boost::urls::url url = {};
|
||||
std::unordered_map<std::string, std::string> headers = {};
|
||||
std::string body = {};
|
||||
inline auto ToString() const -> std::string {
|
||||
std::ostringstream stream;
|
||||
stream << fmt::format("{} {} HTTP/1.1\r\n", this->method, this->url.path());
|
||||
stream << fmt::format("{} {} Http/1.1\r\n", this->method, this->url.path());
|
||||
for(const auto& header : this->headers) {
|
||||
stream << fmt::format("{}: {}\r\n", header.first, header.second);
|
||||
};
|
||||
|
|
|
@ -4,65 +4,65 @@
|
|||
|
||||
namespace cserver::server::http {
|
||||
|
||||
struct HTTPRequestParser : private llhttp_t, public HTTPRequest {
|
||||
struct HttpRequestParser : private llhttp_t, public HttpRequest {
|
||||
bool err = false;
|
||||
bool done = false;
|
||||
std::string headerField = {};
|
||||
std::string headerValue = {};
|
||||
std::string urlString = {};
|
||||
inline HTTPRequestParser(std::string_view data) {
|
||||
inline HttpRequestParser(std::string_view data) {
|
||||
llhttp_settings_t settings;
|
||||
llhttp_settings_init(&settings);
|
||||
settings.on_method = HTTPRequestParser::OnMethod;
|
||||
settings.on_url = HTTPRequestParser::OnUrl;
|
||||
settings.on_url_complete = HTTPRequestParser::OnUrlComplete;
|
||||
settings.on_header_field = HTTPRequestParser::OnHeaderField;
|
||||
settings.on_header_value = HTTPRequestParser::OnHeaderValue;
|
||||
settings.on_headers_complete = HTTPRequestParser::OnHeaderComplete;
|
||||
settings.on_body = HTTPRequestParser::OnBody;
|
||||
settings.on_message_complete = HTTPRequestParser::OnMessageComplete;
|
||||
settings.on_method = HttpRequestParser::OnMethod;
|
||||
settings.on_url = HttpRequestParser::OnUrl;
|
||||
settings.on_url_complete = HttpRequestParser::OnUrlComplete;
|
||||
settings.on_header_field = HttpRequestParser::OnHeaderField;
|
||||
settings.on_header_value = HttpRequestParser::OnHeaderValue;
|
||||
settings.on_headers_complete = HttpRequestParser::OnHeaderComplete;
|
||||
settings.on_body = HttpRequestParser::OnBody;
|
||||
settings.on_message_complete = HttpRequestParser::OnMessageComplete;
|
||||
llhttp_init(this, HTTP_BOTH, &settings);
|
||||
llhttp_execute(this, data.data(), data.size());
|
||||
};
|
||||
static inline auto OnMethod(llhttp_t* parser, const char* data, std::size_t size) -> int {
|
||||
auto* self = static_cast<HTTPRequest*>(static_cast<HTTPRequestParser*>(parser));
|
||||
auto* self = static_cast<HttpRequest*>(static_cast<HttpRequestParser*>(parser));
|
||||
self->method.append(data, size);
|
||||
return 0;
|
||||
};
|
||||
static inline auto OnUrl(llhttp_t* parser, const char* data, std::size_t size) -> int {
|
||||
auto* self = static_cast<HTTPRequestParser*>(parser);
|
||||
auto* self = static_cast<HttpRequestParser*>(parser);
|
||||
self->urlString.append(data, size);
|
||||
return 0;
|
||||
};
|
||||
static inline auto OnUrlComplete(llhttp_t* parser) -> int {
|
||||
auto* self = static_cast<HTTPRequestParser*>(parser);
|
||||
auto* self = static_cast<HttpRequestParser*>(parser);
|
||||
self->url = boost::urls::url(self->urlString);
|
||||
return 0;
|
||||
};
|
||||
static inline auto OnHeaderField(llhttp_t* parser, const char* data, std::size_t size) -> int {
|
||||
auto* self = static_cast<HTTPRequestParser*>(parser);
|
||||
auto* self = static_cast<HttpRequestParser*>(parser);
|
||||
self->headerField.append(data, size);
|
||||
return 0;
|
||||
};
|
||||
static inline auto OnHeaderValue(llhttp_t* parser, const char* data, std::size_t size) -> int {
|
||||
auto* self = static_cast<HTTPRequestParser*>(parser);
|
||||
auto* self = static_cast<HttpRequestParser*>(parser);
|
||||
self->headerValue.append(data, size);
|
||||
return 0;
|
||||
};
|
||||
static inline auto OnHeaderComplete(llhttp_t* parser) -> int {
|
||||
auto* self = static_cast<HTTPRequestParser*>(parser);
|
||||
auto* self = static_cast<HttpRequestParser*>(parser);
|
||||
self->headers.emplace(std::move(self->headerField), std::move(self->headerValue));
|
||||
self->headerValue.clear();
|
||||
self->headerField.clear();
|
||||
return 0;
|
||||
};
|
||||
static inline auto OnBody(llhttp_t* parser, const char* data, std::size_t size) -> int {
|
||||
auto* self = static_cast<HTTPRequestParser*>(parser);
|
||||
auto* self = static_cast<HttpRequestParser*>(parser);
|
||||
self->body.append(data, size);
|
||||
return 0;
|
||||
};
|
||||
static inline auto OnMessageComplete(llhttp_t* parser) -> int {
|
||||
auto* self = static_cast<HTTPRequestParser*>(parser);
|
||||
auto* self = static_cast<HttpRequestParser*>(parser);
|
||||
self->done = true;
|
||||
return 0;
|
||||
};
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
|
||||
namespace cserver::server::http {
|
||||
|
||||
struct HTTPResponse {
|
||||
struct HttpResponse {
|
||||
unsigned short statusCode = 200;
|
||||
std::string statusMessage = "OK";
|
||||
std::unordered_map<std::string, std::string> headers = {};
|
||||
std::string body = {};
|
||||
inline auto ToString() const -> std::string {
|
||||
std::ostringstream stream;
|
||||
stream << fmt::format("HTTP/1.1 {} {}\r\n", this->statusCode, this->statusMessage);
|
||||
stream << fmt::format("Http/1.1 {} {}\r\n", this->statusCode, this->statusMessage);
|
||||
for(const auto& header : this->headers) {
|
||||
stream << fmt::format("{}: {}\r\n", header.first, header.second);
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
namespace cserver::server::http {
|
||||
|
||||
struct HTTPStream {
|
||||
struct HttpStream {
|
||||
boost::asio::ip::tcp::socket socket;
|
||||
std::stringstream stream = {};
|
||||
inline auto SetMethod(std::string method) -> Task<void> {
|
||||
|
@ -13,7 +13,7 @@ struct HTTPStream {
|
|||
co_await boost::asio::async_write(this->socket, boost::asio::buffer(method.data(), method.size()), boost::asio::transfer_all(), boost::asio::use_awaitable);
|
||||
};
|
||||
inline auto SetStatus(std::string status) -> Task<void> {
|
||||
status = fmt::format("HTTP/1.1 {}\r\n", std::move(status));
|
||||
status = fmt::format("Http/1.1 {}\r\n", std::move(status));
|
||||
co_await boost::asio::async_write(this->socket, boost::asio::buffer(status.data(), status.size()), boost::asio::transfer_all(), boost::asio::use_awaitable);
|
||||
};
|
||||
|
||||
|
|
|
@ -49,13 +49,13 @@ struct Server : StopBlocker {
|
|||
Server(std::index_sequence_for<Ts...>{}, name, context) {
|
||||
};
|
||||
template<auto I, typename Socket>
|
||||
auto ProcessHandler(Socket&& socket, http::HTTPRequest request) -> Task<void> {
|
||||
if constexpr(requires(http::HTTPStream& stream){Get<I>(this->handlers).HandleRequestStream(std::move(request), stream);}) {
|
||||
http::HTTPStream stream{std::move(socket)};
|
||||
auto ProcessHandler(Socket&& socket, http::HttpRequest request) -> Task<void> {
|
||||
if constexpr(requires(http::HttpStream& stream){Get<I>(this->handlers).HandleRequestStream(std::move(request), stream);}) {
|
||||
http::HttpStream stream{std::move(socket)};
|
||||
co_await Get<I>(this->handlers).HandleRequestStream(std::move(request), stream);
|
||||
co_return;
|
||||
} else {
|
||||
http::HTTPResponse response = co_await Get<I>(this->handlers).HandleRequest(std::move(request));
|
||||
http::HttpResponse response = co_await Get<I>(this->handlers).HandleRequest(std::move(request));
|
||||
response.headers["Content-Length"] = std::to_string(response.body.size());
|
||||
response.headers["Server"] = "cserver/1";
|
||||
auto data = response.ToString();
|
||||
|
@ -67,7 +67,7 @@ struct Server : StopBlocker {
|
|||
std::string buffer;
|
||||
buffer.reserve(socket.available());
|
||||
co_await boost::asio::async_read_until(socket, boost::asio::dynamic_buffer(buffer), "\r\n\r\n", boost::asio::use_awaitable);
|
||||
http::HTTPRequest request = http::HTTPRequestParser{buffer};
|
||||
http::HttpRequest request = http::HttpRequestParser{buffer};
|
||||
bool flag = false;
|
||||
co_await [&]<auto... Is>(std::index_sequence<Is...>) -> cserver::Task<void> {
|
||||
(co_await [&] -> cserver::Task<void> {
|
||||
|
@ -76,7 +76,7 @@ struct Server : StopBlocker {
|
|||
};
|
||||
}(), ...);
|
||||
}(std::index_sequence_for<Ts...>());
|
||||
constexpr std::string_view error404 = "HTTP/1.1 404 Not Found\r\n"
|
||||
constexpr std::string_view error404 = "Http/1.1 404 Not Found\r\n"
|
||||
"Content-Length: 0\r\n"
|
||||
"\r\n";
|
||||
if(!flag) {
|
||||
|
|
Loading…
Reference in a new issue