From ac323fa741b3805a2c62180f0fa8553f28157e94 Mon Sep 17 00:00:00 2001 From: LeonardoBizzoni Date: Thu, 15 Aug 2024 17:01:01 +0200 Subject: [PATCH] Removed fields from Request in favour of map to allow optional field Also renamed the `ERR` macro to `Err` and changed `NEW_LINE` from a C macro to a `constexpr` --- src/http.h | 5 +++-- src/listener.cpp | 8 ++++---- src/request.cpp | 4 +--- src/request.h | 5 +++-- src/response.cpp | 6 +++--- src/send.cpp | 20 ++++++++++++-------- 6 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/http.h b/src/http.h index eec9f75..87d16f3 100644 --- a/src/http.h +++ b/src/http.h @@ -8,10 +8,11 @@ #include "response.h" #include "listener.h" -#define ERR(error) std::unexpected(error) -#define NEW_LINE std::string_view("\r\n") +#define Err(error) std::unexpected(error) namespace http { + constexpr std::string_view NEW_LINE = "\r\n"; + std::expected send(Method, const Request& req); std::expected connect(const std::string_view& domain_name, const uint16_t port = 80); diff --git a/src/listener.cpp b/src/listener.cpp index 4ff4ff8..31bb3fe 100644 --- a/src/listener.cpp +++ b/src/listener.cpp @@ -19,7 +19,7 @@ namespace http { uint32_t opt = 1; if (server.socketfd < 0 || ::setsockopt(server.socketfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) < 0) { - return ERR(Error::SocketCreation); + return Err(Error::SocketCreation); } server.addr.sin_family = AF_INET; @@ -27,11 +27,11 @@ namespace http { server.addr.sin_port = htons(port); if (::bind(server.socketfd, (struct sockaddr *)&server.addr, sizeof(server.addr)) < 0) { - return ERR(Error::SocketBind); + return Err(Error::SocketBind); } if (::listen(server.socketfd, backlog) < 0) { - return ERR(Error::SocketListen); + return Err(Error::SocketListen); } return server; @@ -41,7 +41,7 @@ namespace http { socklen_t addrsize = sizeof(this->addr); int8_t clientfd = ::accept(this->socketfd, (struct sockaddr *)&this->addr, &addrsize); if (clientfd < 0) { - return ERR(Error::SocketConnection); + return Err(Error::SocketConnection); } auto raw_req = read_raw_message(clientfd); diff --git a/src/request.cpp b/src/request.cpp index 5908c2b..0b19434 100644 --- a/src/request.cpp +++ b/src/request.cpp @@ -4,7 +4,5 @@ std::ostream &operator<<(std::ostream &os, const http::Request &req) { return os << "Request { domain: " << std::quoted(req.domain_name) << ", port: " << req.port - << ", host: " << std::quoted(req.host) << ", query: " << std::quoted(req.query) - << ", accept: " << std::quoted(req.accept) << ", body: " << std::quoted(req.body) - << " }"; + << ", query: " << std::quoted(req.query) << ", body: " << std::quoted(req.body) << " }"; } diff --git a/src/request.h b/src/request.h index 262261b..2705113 100644 --- a/src/request.h +++ b/src/request.h @@ -3,6 +3,7 @@ #include #include #include +#include namespace http { struct http_version { @@ -13,12 +14,12 @@ namespace http { struct Request { uint16_t port = 80; std::string_view domain_name; - std::string_view host = domain_name; std::string_view query = "/"; - std::string_view accept = "*/*"; std::string_view body = ""; http_version version = {.major = 1, .minor = 1}; + + std::unordered_map optheaders = {}; }; } // namespace http diff --git a/src/response.cpp b/src/response.cpp index cc81be1..4b02413 100644 --- a/src/response.cpp +++ b/src/response.cpp @@ -8,7 +8,7 @@ namespace http { std::expected Response::build(std::string_view raw_response) noexcept { if (raw_response.empty()) { - return ERR(Error::InvalidResponse); + return Err(Error::InvalidResponse); } Response resp; @@ -27,14 +27,14 @@ namespace http { resp.version = {.major = (uint8_t)std::stoi(major.data()), .minor = (uint8_t)std::stoi(minor.data())}; } catch (...) { - return ERR(Error::InvalidResponseHTTPVersion); + return Err(Error::InvalidResponseHTTPVersion); } try { std::string_view status(*++word_iter); resp.status = status_map[std::stoi(status.data())]; } catch (...) { - return ERR(Error::InvalidResponseStatusCode); + return Err(Error::InvalidResponseStatusCode); } for (std::string_view line; lines_view_iter != lines_view.end() && diff --git a/src/send.cpp b/src/send.cpp index ee8ed64..f4dacca 100644 --- a/src/send.cpp +++ b/src/send.cpp @@ -24,7 +24,7 @@ namespace http { hints.ai_socktype = SOCK_STREAM; // TCP only if (getaddrinfo(domain_name.data(), std::to_string(port).c_str(), &hints, &addr_list)) { - return ERR(Error::DNSResolution); + return Err(Error::DNSResolution); } int8_t remote_socketfd; @@ -33,7 +33,7 @@ namespace http { socket(it->second.ai_family, it->second.ai_socktype, it->second.ai_protocol); if (remote_socketfd < 0) { close(remote_socketfd); - return ERR(Error::SocketConnection); + return Err(Error::SocketConnection); } } else { struct addrinfo *remote = 0; @@ -65,7 +65,7 @@ namespace http { if (!remote) { freeaddrinfo(addr_list); - return ERR(Error::ServerNotFound); + return Err(Error::ServerNotFound); } ip_map[domain_name.data()] = *remote; @@ -79,7 +79,7 @@ namespace http { auto maybe_socketfd = connect(req.domain_name, req.port); if (!maybe_socketfd.has_value()) { - return ERR(maybe_socketfd.error()); + return Err(maybe_socketfd.error()); } std::string msg = build_request(method, req); @@ -87,7 +87,7 @@ namespace http { auto maybe_response = read_raw_message(maybe_socketfd.value()); if (!maybe_response.has_value()) { - return ERR(maybe_response.error()); + return Err(maybe_response.error()); } close(maybe_socketfd.value()); @@ -98,11 +98,15 @@ namespace http { std::stringstream ss; ss << method << " " << req.query << " HTTP/" << (int)req.version.major << "." << (int)req.version.minor << NEW_LINE; - ss << "Host: " << req.host << NEW_LINE; - ss << "Accept: " << req.accept << NEW_LINE; + ss << "Host: " << req.domain_name << NEW_LINE; + + for (const auto &header : req.optheaders) { + ss << header.first << ": " << header.second << NEW_LINE; + } if (!req.body.empty()) { - ss << "Content-Length: " << req.body.length() << NEW_LINE << NEW_LINE << req.body; + ss << "Content-Length: " << req.body.length() * sizeof(char) << NEW_LINE << NEW_LINE + << req.body; } else { ss << NEW_LINE; } -- 2.52.0