small fixes

This commit is contained in:
Benedek László 2024-05-17 01:47:31 +02:00
parent 141ac52f7d
commit 8dc707cf6b
6 changed files with 82 additions and 33 deletions

View File

@ -3,36 +3,45 @@ cmake_minimum_required(VERSION 3.25)
project(Rum VERSION 1.0) project(Rum VERSION 1.0)
# compiler setup # compiler setup
set(CMAKE_CXX_COMPILER "clang++") set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror") # warnings set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++2b") # std c++23
if (STATIC) set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static") # static set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()
if (DEBUG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") # debug symbols
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2") # optimisations
# IDE setup (clangd)
set(CMAKE_EXPORT_COMPILE_COMMANDS true) set(CMAKE_EXPORT_COMPILE_COMMANDS true)
file(GLOB_RECURSE SOURCES "${CMAKE_SOURCE_DIR}/src/*.cpp") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -Wno-unused-parameter -Wno-unused-variable -Wno-unused-private-field")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -Wno-unused-parameter -Wno-unused-variable -Wno-unused-private-field")
add_executable(server.bin ${SOURCES}) file(GLOB_RECURSE SOURCES "${CMAKE_SOURCE_DIR}/src/rum/*.cpp")
set(HEADERS "${CMAKE_SOURCE_DIR}/inc/rum")
add_library(rum OBJECT ${SOURCES})
set_target_properties(rum PROPERTIES POSITION_INDEPENDENT_CODE 1)
target_include_directories(rum PUBLIC "${CMAKE_SOURCE_DIR}/inc")
target_include_directories(server.bin PRIVATE "${CMAKE_SOURCE_DIR}/inc") add_library(rum-static STATIC $<TARGET_OBJECTS:rum>)
set_target_properties(rum-static PROPERTIES OUTPUT_NAME rum)
target_include_directories(rum-static PUBLIC "${CMAKE_SOURCE_DIR}/inc")
add_custom_target(run add_library(rum-shared SHARED $<TARGET_OBJECTS:rum>)
COMMAND $<TARGET_FILE:server.bin> set_target_properties(rum-shared PROPERTIES OUTPUT_NAME rum)
DEPENDS server.bin target_include_directories(rum-shared PUBLIC "${CMAKE_SOURCE_DIR}/inc")
COMMENT "Running server.bin"
add_executable(example "${CMAKE_SOURCE_DIR}/src/server.cpp")
target_link_libraries(example rum-shared)
if(USE_FLAGS)
target_link_libraries(example flags-cpp)
endif()
install(TARGETS
rum-static
rum-shared
RUNTIME
COMPONENT Runtime
LIBRARY
COMPONENT Runtime
ARCHIVE
COMPONENT Development
) )
install(DIRECTORY ${HEADERS} DESTINATION include COMPONENT Development)
add_custom_target(docker
COMMAND docker build -t dowerx/rum:${CMAKE_PROJECT_VERSION} ..
COMMENT "Building docker image"
)

View File

@ -13,6 +13,7 @@ class Request {
Method get_method() const { return method; } Method get_method() const { return method; }
URI& get_uri() { return uri; } URI& get_uri() { return uri; }
URI copy_uri() const { return uri; }
const std::map<std::string, std::string>& get_headers() const { return headers; } const std::map<std::string, std::string>& get_headers() const { return headers; }
std::string get_header(std::string name) const { return headers.at(name); } std::string get_header(std::string name) const { return headers.at(name); }

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include <format>
#include <map> #include <map>
#include <string> #include <string>

View File

@ -2,8 +2,11 @@
#include <rum/tcp/error.h> #include <rum/tcp/error.h>
#include <rum/tcp/server.h> #include <rum/tcp/server.h>
#include <rum/tcp/utility.h> #include <rum/tcp/utility.h>
#include <algorithm>
#include <cstddef>
#include <iostream> #include <iostream>
#include <regex> #include <regex>
#include <stdexcept>
#include <string> #include <string>
namespace Rum::HTTP { namespace Rum::HTTP {
@ -28,8 +31,11 @@ Server::Server(unsigned int port, size_t worker_count, size_t buffer_size) : Rum
tasks.pop(); tasks.pop();
} }
#ifdef DEBUG
std::cout << "Worker #" << i << " accepted a connection." << std::endl; std::cout << "Worker #" << i << " accepted a connection." << std::endl;
#else
(void)i;
#endif
handler(task.client_sock, task.sockaddr, buffer); handler(task.client_sock, task.sockaddr, buffer);
if (int status = close(task.client_sock); status == TCP::Error::UNKNOWN) { if (int status = close(task.client_sock); status == TCP::Error::UNKNOWN) {
std::cerr << TCP::to_string(task.sockaddr) << ": " << TCP::Error((TCP::Error::Type)status).what() << std::endl; std::cerr << TCP::to_string(task.sockaddr) << ": " << TCP::Error((TCP::Error::Type)status).what() << std::endl;
@ -37,7 +43,9 @@ Server::Server(unsigned int port, size_t worker_count, size_t buffer_size) : Rum
} }
}); });
workers.emplace_back(std::move(worker)); workers.emplace_back(std::move(worker));
#ifdef DEBUG
std::cout << "Worker #" << i << " created" << std::endl; std::cout << "Worker #" << i << " created" << std::endl;
#endif
} }
} }
@ -88,8 +96,9 @@ Method string_to_method(std::string text) {
void Server::handler(int client_sock, const sockaddr_in& client_address, char* buffer) { void Server::handler(int client_sock, const sockaddr_in& client_address, char* buffer) {
std::string address = TCP::to_string(client_address); std::string address = TCP::to_string(client_address);
#ifdef DEBUG
std::cout << address << ": connected" << std::endl; std::cout << address << ": connected" << std::endl;
#endif
Request request; Request request;
enum Stage { METHOD, HEADER, BODY }; enum Stage { METHOD, HEADER, BODY };
@ -152,10 +161,13 @@ void Server::handler(int client_sock, const sockaddr_in& client_address, char* b
} }
} }
} else { } else {
request.set_header(it->str(1), it->str(2)); std::string key(it->str(1));
std::transform(key.begin(), key.end(), key.begin(), [](unsigned char c) { return std::tolower(c); });
request.set_header(key, it->str(2));
} }
} }
message = message.substr(message.find("\r\n\r\n"));
message = message.substr(message.find("\r\n\r\n") + 4);
if (Method method = request.get_method(); method == POST || method == PUT) if (Method method = request.get_method(); method == POST || method == PUT)
stage = BODY; stage = BODY;
@ -164,6 +176,17 @@ void Server::handler(int client_sock, const sockaddr_in& client_address, char* b
} }
if (stage == BODY) { if (stage == BODY) {
std::cout << "here" << std::endl;
try {
size_t content_length = std::stoul(request.get_header("content-length"));
std::cout << message.size() << " " << content_length << std::endl;
if (message.size() < content_length)
continue;
} catch (std::out_of_range) {
} catch (std::invalid_argument e) {
std::cerr << "invlaid Content-Length header" << std::endl;
}
request.set_body(message); request.set_body(message);
break; break;
} }

View File

@ -2,6 +2,7 @@
#include <exception> #include <exception>
#include <iostream> #include <iostream>
#include <regex> #include <regex>
#include <format>
#include <string> #include <string>
namespace Rum::HTTP { namespace Rum::HTTP {
@ -27,11 +28,13 @@ URI::operator std::string() const {
} }
URI::URI(const std::string& uri) { URI::URI(const std::string& uri) {
std::regex uri_regex(R"((([\w\d]+):\/\/)?(([\w\d]+)(:([\w\d]+)?)@)?([\w\d\.]+)(:(\d+))?(\/?[\w\d\.\/]+)?(\?([\w\d\=\&]+))?(\#([\w\d]*))?)"); std::regex uri_regex(R"((([\w\d]+):\/\/)?(([\w\d]+)(:([\w\d]+)?)@)?([\w\d\.]+)(:(\d+))?(\/?[\w\d\.\/]+)?(\?([^#]+))?(\#([\w\d]*))?)");
std::smatch match; std::smatch match;
#ifdef DEBUG
std::cout << uri << std::endl; std::cout << uri << std::endl;
#endif
if (std::regex_match(uri.cbegin(), uri.cend(), match, uri_regex)) { if (std::regex_match(uri.cbegin(), uri.cend(), match, uri_regex)) {
#define MATCH(var, i) \ #define MATCH(var, i) \

View File

@ -1,4 +1,6 @@
#include <flags/flags.h> #ifdef USE_FLAGS
#include <flags-cpp/flags-cpp.h>
#endif
#include <rum/http/http.h> #include <rum/http/http.h>
#include <rum/tcp/error.h> #include <rum/tcp/error.h>
#include <csignal> #include <csignal>
@ -7,6 +9,8 @@
Rum::HTTP::Server* server; Rum::HTTP::Server* server;
int main(int argc, char** argv) { int main(int argc, char** argv) {
#ifdef USE_FLAGS
Flags::Parser parser; Flags::Parser parser;
int* port = parser.add<int>("port", "tcp port number", false, 8080); int* port = parser.add<int>("port", "tcp port number", false, 8080);
unsigned long int* workers = parser.add<unsigned long int>("workers", "number of worker threads", false, 10); unsigned long int* workers = parser.add<unsigned long int>("workers", "number of worker threads", false, 10);
@ -18,6 +22,11 @@ int main(int argc, char** argv) {
return -1; return -1;
} }
#else
int* port = new int(argc >= 2 ? atoi(argv[1]) : 8080);
unsigned long* workers = new unsigned long(10);
#endif
std::cout << "Port: " << *port << std::endl; std::cout << "Port: " << *port << std::endl;
std::cout << "Workers: " << *workers << std::endl; std::cout << "Workers: " << *workers << std::endl;
@ -37,10 +46,15 @@ int main(int argc, char** argv) {
server->add_path<Rum::HTTP::GET>("/cookie", [](const Rum::HTTP::Request& req, Rum::HTTP::Response& resp) { server->add_path<Rum::HTTP::GET>("/cookie", [](const Rum::HTTP::Request& req, Rum::HTTP::Response& resp) {
std::cout << "request accepted" << std::endl; std::cout << "request accepted" << std::endl;
resp.cookies.push_back(Rum::HTTP::Cookie("testCookie", "valueOfCookie", "/", 60*60)); resp.cookies.push_back(Rum::HTTP::Cookie("testCookie", "valueOfCookie", "/", 60 * 60));
resp.body = "<h1>Cookie</h1><pre>" + (std::string)req + "</pre>"; resp.body = "<h1>Cookie</h1><pre>" + (std::string)req + "</pre>";
}); });
server->add_path<Rum::HTTP::POST>("/add", [](const Rum::HTTP::Request& req, Rum::HTTP::Response& resp) {
std::cout << (std::string)req << std::endl;
resp.body = "<h1>Hello World</h1><pre>" + (std::string)req + "</pre>";
});
server->add_path<Rum::HTTP::GET>("/.*", [](const Rum::HTTP::Request& req, Rum::HTTP::Response& resp) { server->add_path<Rum::HTTP::GET>("/.*", [](const Rum::HTTP::Request& req, Rum::HTTP::Response& resp) {
std::cout << "request accepted" << std::endl; std::cout << "request accepted" << std::endl;
resp.body = "<h1>Hello World</h1><pre>" + (std::string)req + "</pre>"; resp.body = "<h1>Hello World</h1><pre>" + (std::string)req + "</pre>";