]> git.leonardobizzoni.com Git - http-lib/commitdiff
Sending response to client
authorLeonardoBizzoni <leo2002714@gmail.com>
Fri, 16 Aug 2024 06:21:19 +0000 (08:21 +0200)
committerLeonardoBizzoni <leo2002714@gmail.com>
Fri, 16 Aug 2024 06:21:19 +0000 (08:21 +0200)
CMakeLists.txt
src/const_definitions.h
src/http_version.h [deleted file]
src/listener.cpp
src/main.cpp [deleted file]
src/request.h
src/response.cpp
src/response.h

index 162043ddc3aa574bdd1cca636eda8c293fed8e12..ce95a5f306373747e898f44490797ff2f7275e0c 100644 (file)
@@ -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
index 507854ec519fa2e38fee18974771fa951fc7f52c..96cdccc25a52bde68a3ad333113eed67617ed3a4 100644 (file)
@@ -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 (file)
index 7bc19ba..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma once
-
-#include <cstdint>
-
-namespace http {
-  struct http_version {
-    uint8_t major = 1;
-    uint8_t minor = 1;
-  };
-}  // namespace http
index 2dca863f0a84195c3527f0a4f6917de92c532b83..5222475ec5d56c7a071b361962aa585e96f2b224 100644 (file)
@@ -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 (file)
index ace77e4..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <iostream>
-
-#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();
-}
index 3a4bd4d2c408458cfda010b794813590f09ac711..2087327a1ae98325a560985ce4d629c0f0a22316 100644 (file)
@@ -7,7 +7,7 @@
 #include <unordered_map>
 
 #include "error.h"
-#include "http_version.h"
+#include "const_definitions.h"
 #include "method.h"
 
 namespace http {
index d3be232dc29a153ae72ed23d4f206599c846f7a1..0e66bd392cf5a122ca1a80a56dbdb89afedfc351 100644 (file)
@@ -1,9 +1,14 @@
 #include "response.h"
+#include <sys/socket.h>
+
 #include <expected>
 #include <iostream>
 #include <ranges>
+#include <sstream>
 #include <utility>
 
+#include "const_definitions.h"
+
 namespace http {
   std::expected<Response, Error> 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();
   }
index 11d64eeb74efa101f8bfc1f51d3efe4a4d11693d..12725322b05a038abc6eed97b870f4e09ecd8012 100644 (file)
@@ -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<std::string, std::string> fields;
 
   public:
-    Response() : version({1,1}), status(Status::NOT_ACCEPTABLE) {}
+    Response() : version({1,1}), status(Status::NOT_FOUND) {}
     ~Response() {}
 
     static std::expected<Response, Error> build(std::string_view raw_response) noexcept;
+
+    void send(uint8_t sockfd);
   };
 }  // namespace http