From: LeonardoBizzoni Date: Fri, 16 Aug 2024 06:21:19 +0000 (+0200) Subject: Sending response to client X-Git-Url: http://git.leonardobizzoni.com/?a=commitdiff_plain;h=260f3e264d8f38b9bb0a425c6db96932c6b093bc;p=http-lib Sending response to client --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 162043d..ce95a5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,14 +16,13 @@ set(CMAKE_ARCHITE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) # Set output directories -set(OUTPUT_DIR "${PROJECT_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") +# set(OUTPUT_DIR "${PROJECT_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") file(GLOB SRC "src/*.cpp" "src/*.hpp" "src/*.h") -add_executable(${PROJECT_NAME} ${SRC}) +add_library(${PROJECT_NAME} ${SRC}) target_sources(${PROJECT_NAME} PRIVATE ${PLATFORM_SRC}) target_compile_definitions(${PROJECT_NAME} PRIVATE ROOTDIR="${CMAKE_SOURCE_DIR}") -target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic -Werror) # Set output directories set_target_properties(${PROJECT_NAME} PROPERTIES diff --git a/src/const_definitions.h b/src/const_definitions.h index 507854e..96cdccc 100644 --- a/src/const_definitions.h +++ b/src/const_definitions.h @@ -142,4 +142,9 @@ namespace http { {510, Status::NOT_EXTENDED}, {511, Status::NETWORK_AUTHENTICATION_REQUIRED}, }; -} + + struct http_version { + uint8_t major = 1; + uint8_t minor = 1; + }; +} // namespace http diff --git a/src/http_version.h b/src/http_version.h deleted file mode 100644 index 7bc19ba..0000000 --- a/src/http_version.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include - -namespace http { - struct http_version { - uint8_t major = 1; - uint8_t minor = 1; - }; -} // namespace http diff --git a/src/listener.cpp b/src/listener.cpp index 2dca863..5222475 100644 --- a/src/listener.cpp +++ b/src/listener.cpp @@ -64,7 +64,7 @@ namespace http { } } - // Send `resp` to client + resp.send(clientfd); ::shutdown(clientfd, SHUT_RDWR); ::close(clientfd); diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index ace77e4..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include - -#include "http.h" -#include "request.h" -#include "response.h" - -int main() { - auto server = http::Listener::on_local(8800); - server.value().routes["/"] = [](const http::Request &req) -> http::Response { - std::cout << req << std::endl; - return http::Response(); - }; - server.value().routes["/prova"] = [](const http::Request &req) -> http::Response { - std::cout << "Hello, World!" << std::endl; - auto _ = req.body; - return http::Response(); - }; - server.value().serve(); -} diff --git a/src/request.h b/src/request.h index 3a4bd4d..2087327 100644 --- a/src/request.h +++ b/src/request.h @@ -7,7 +7,7 @@ #include #include "error.h" -#include "http_version.h" +#include "const_definitions.h" #include "method.h" namespace http { diff --git a/src/response.cpp b/src/response.cpp index d3be232..0e66bd3 100644 --- a/src/response.cpp +++ b/src/response.cpp @@ -1,9 +1,14 @@ #include "response.h" +#include + #include #include #include +#include #include +#include "const_definitions.h" + namespace http { std::expected Response::build(std::string_view raw_response) noexcept { if (raw_response.empty()) { @@ -53,6 +58,26 @@ namespace http { return resp; } + + void Response::send(uint8_t sockfd) { + std::stringstream ss; + ss << "HTTP/" << (int)this->version.major << "." << (int)this->version.minor << " " << this->status + << NEW_LINE; + + for (const auto &field : this->fields) { + ss << field.first << ": " << field.second << NEW_LINE; + } + + if (!this->body.empty()) { + ss << "Content-Length: " << this->body.size() * sizeof(char) << NEW_LINE << NEW_LINE + << this->body; + } else { + ss << NEW_LINE; + } + + std::string msg = ss.str(); + ::send((int)sockfd, msg.c_str(), msg.size(), 0); + } } // namespace http std::ostream &operator<<(std::ostream &os, const http::Status &status) { @@ -60,129 +85,129 @@ std::ostream &operator<<(std::ostream &os, const http::Status &status) { switch (status) { case Status::CONTINUE: - return os << (uint16_t)status << " - Continue"; + return os << (uint16_t)status << " Continue"; case Status::SWITCHING_PROTOCOLS: - return os << (uint16_t)status << " - Switching Protocols"; + return os << (uint16_t)status << " Switching Protocols"; case Status::PROCESSING: - return os << (uint16_t)status << " - Processing"; + return os << (uint16_t)status << " Processing"; case Status::OK: - return os << (uint16_t)status << " - OK"; + return os << (uint16_t)status << " OK"; case Status::CREATED: - return os << (uint16_t)status << " - Created"; + return os << (uint16_t)status << " Created"; case Status::ACCEPTED: - return os << (uint16_t)status << " - Accepted"; + return os << (uint16_t)status << " Accepted"; case Status::NON_AUTHORITATIVE_INFORMATION: - return os << (uint16_t)status << " - Non-Authoritative Information"; + return os << (uint16_t)status << " Non-Authoritative Information"; case Status::NO_CONTENT: - return os << (uint16_t)status << " - No Content"; + return os << (uint16_t)status << " No Content"; case Status::PARTIAL_CONTENT: - return os << (uint16_t)status << " - Partial Content"; + return os << (uint16_t)status << " Partial Content"; case Status::ALREADY_REPORTED: - return os << (uint16_t)status << " - Already Reported"; + return os << (uint16_t)status << " Already Reported"; case Status::IM_USED: - return os << (uint16_t)status << " - IM Used"; + return os << (uint16_t)status << " IM Used"; case Status::MULTIPLE_CHOICES: - return os << (uint16_t)status << " - Multiple Choices"; + return os << (uint16_t)status << " Multiple Choices"; case Status::MOVED_PERMANENTLY: - return os << (uint16_t)status << " - Moved Permanently"; + return os << (uint16_t)status << " Moved Permanently"; case Status::FOUND: - return os << (uint16_t)status << " - Found"; + return os << (uint16_t)status << " Found"; case Status::SEE_OTHER: - return os << (uint16_t)status << " - See Other"; + return os << (uint16_t)status << " See Other"; case Status::NOT_MODIFIED: - return os << (uint16_t)status << " - Not Modified"; + return os << (uint16_t)status << " Not Modified"; case Status::USE_PROXY: - return os << (uint16_t)status << " - Use Proxy"; + return os << (uint16_t)status << " Use Proxy"; case Status::UNUSED: - return os << (uint16_t)status << " - Unused"; + return os << (uint16_t)status << " Unused"; case Status::TEMPORARY_REDIRECT: - return os << (uint16_t)status << " - Temporary Redirect"; + return os << (uint16_t)status << " Temporary Redirect"; case Status::PERMANENT_REDIRECT: - return os << (uint16_t)status << " - Permanent Redirect"; + return os << (uint16_t)status << " Permanent Redirect"; case Status::BAD_REQUEST: - return os << (uint16_t)status << " - Bad Request"; + return os << (uint16_t)status << " Bad Request"; case Status::UNAUTHORIZED: - return os << (uint16_t)status << " - Unauthorized"; + return os << (uint16_t)status << " Unauthorized"; case Status::PAYMENT_REQUIRED: - return os << (uint16_t)status << " - Payment Required"; + return os << (uint16_t)status << " Payment Required"; case Status::FORBIDDEN: - return os << (uint16_t)status << " - Forbidden"; + return os << (uint16_t)status << " Forbidden"; case Status::NOT_FOUND: - return os << (uint16_t)status << " - Not Found"; + return os << (uint16_t)status << " Not Found"; case Status::METHOD_NOT_ALLOWED: - return os << (uint16_t)status << " - Method Not Allowed"; + return os << (uint16_t)status << " Method Not Allowed"; case Status::NOT_ACCEPTABLE: - return os << (uint16_t)status << " - Not Acceptable"; + return os << (uint16_t)status << " Not Acceptable"; case Status::PROXY_AUTHENTICATION_REQUIRED: - return os << (uint16_t)status << " - Proxy Authentication Required"; + return os << (uint16_t)status << " Proxy Authentication Required"; case Status::REQUEST_TIMEOUT: - return os << (uint16_t)status << " - Request Timeout"; + return os << (uint16_t)status << " Request Timeout"; case Status::CONFLICT: - return os << (uint16_t)status << " - Conflict"; + return os << (uint16_t)status << " Conflict"; case Status::GONE: - return os << (uint16_t)status << " - Gone"; + return os << (uint16_t)status << " Gone"; case Status::LENGTH_REQUIRED: - return os << (uint16_t)status << " - Length Required"; + return os << (uint16_t)status << " Length Required"; case Status::PRECONDITION_FAILED: - return os << (uint16_t)status << " - Precondition Failed"; + return os << (uint16_t)status << " Precondition Failed"; case Status::PAYLOAD_TOO_LARGE: - return os << (uint16_t)status << " - Payload Too Large"; + return os << (uint16_t)status << " Payload Too Large"; case Status::URI_TOO_LONG: - return os << (uint16_t)status << " - URI Too Long"; + return os << (uint16_t)status << " URI Too Long"; case Status::UNSUPPORTED_MEDIA_TYPE: - return os << (uint16_t)status << " - Unsupported Media Type"; + return os << (uint16_t)status << " Unsupported Media Type"; case Status::RANGE_NOT_SATISFIABLE: - return os << (uint16_t)status << " - Range Not Satisfiable"; + return os << (uint16_t)status << " Range Not Satisfiable"; case Status::EXPECTATION_FAILED: - return os << (uint16_t)status << " - Expectation Failed"; + return os << (uint16_t)status << " Expectation Failed"; case Status::IM_A_TEAPOT: - return os << (uint16_t)status << " - I'm a teapot"; + return os << (uint16_t)status << " I'm a teapot"; case Status::MISDIRECTED_REQUEST: - return os << (uint16_t)status << " - Misdirected Request"; + return os << (uint16_t)status << " Misdirected Request"; case Status::UNPROCESSABLE_CONTENT: - return os << (uint16_t)status << " - Unprocessable Content"; + return os << (uint16_t)status << " Unprocessable Content"; case Status::LOCKED: - return os << (uint16_t)status << " - Locked"; + return os << (uint16_t)status << " Locked"; case Status::FAILED_DEPENDENCY: - return os << (uint16_t)status << " - Failed Dependency"; + return os << (uint16_t)status << " Failed Dependency"; case Status::TOO_EARLY: - return os << (uint16_t)status << " - Too Early"; + return os << (uint16_t)status << " Too Early"; case Status::UPGRADE_REQUIRED: - return os << (uint16_t)status << " - Upgrade Required"; + return os << (uint16_t)status << " Upgrade Required"; case Status::PRECONDITION_REQUIRED: - return os << (uint16_t)status << " - Precondition Required"; + return os << (uint16_t)status << " Precondition Required"; case Status::TOO_MANY_REQUESTS: - return os << (uint16_t)status << " - Too Many Requests"; + return os << (uint16_t)status << " Too Many Requests"; case Status::REQUEST_HEADER_FIELDS_TOO_LARGE: - return os << (uint16_t)status << " - Request Header Fields Too Large"; + return os << (uint16_t)status << " Request Header Fields Too Large"; case Status::UNAVAILABLE_FOR_LEGAL_REASONS: - return os << (uint16_t)status << " - Unavailable For Legal Reasons"; + return os << (uint16_t)status << " Unavailable For Legal Reasons"; case Status::INTERNAL_SERVER_ERROR: - return os << (uint16_t)status << " - Internal Server Error"; + return os << (uint16_t)status << " Internal Server Error"; case Status::NOT_IMPLEMENTED: - return os << (uint16_t)status << " - Not Implemented"; + return os << (uint16_t)status << " Not Implemented"; case Status::BAD_GATEWAY: - return os << (uint16_t)status << " - Bad Gateway"; + return os << (uint16_t)status << " Bad Gateway"; case Status::SERVICE_UNAVAILABLE: - return os << (uint16_t)status << " - Service Unavailable"; + return os << (uint16_t)status << " Service Unavailable"; case Status::GATEWAY_TIMEOUT: - return os << (uint16_t)status << " - Gateway Timeout"; + return os << (uint16_t)status << " Gateway Timeout"; case Status::HTTP_VERSION_NOT_SUPPORTED: - return os << (uint16_t)status << " - HTTP Version Not Supported"; + return os << (uint16_t)status << " HTTP Version Not Supported"; case Status::VARIANT_ALSO_NEGOTIATES: - return os << (uint16_t)status << " - Variant Also Negotiates"; + return os << (uint16_t)status << " Variant Also Negotiates"; case Status::INSUFFICIENT_STORAGE: - return os << (uint16_t)status << " - Insufficient Storage"; + return os << (uint16_t)status << " Insufficient Storage"; case Status::LOOP_DETECTED: - return os << (uint16_t)status << " - Loop Detected"; + return os << (uint16_t)status << " Loop Detected"; case Status::NOT_EXTENDED: - return os << (uint16_t)status << " - Not Extended"; + return os << (uint16_t)status << " Not Extended"; case Status::NETWORK_AUTHENTICATION_REQUIRED: - return os << (uint16_t)status << " - Network Authentication Required"; + return os << (uint16_t)status << " Network Authentication Required"; default: std::unreachable(); } diff --git a/src/response.h b/src/response.h index 11d64ee..1272532 100644 --- a/src/response.h +++ b/src/response.h @@ -5,7 +5,6 @@ #include "const_definitions.h" #include "error.h" -#include "http_version.h" namespace http { struct Response { @@ -15,10 +14,12 @@ namespace http { std::unordered_map fields; public: - Response() : version({1,1}), status(Status::NOT_ACCEPTABLE) {} + Response() : version({1,1}), status(Status::NOT_FOUND) {} ~Response() {} static std::expected build(std::string_view raw_response) noexcept; + + void send(uint8_t sockfd); }; } // namespace http