From 63fd2b7ccab0f78d0e8a996062d4655c61a81498 Mon Sep 17 00:00:00 2001 From: = Date: Mon, 16 Dec 2024 16:41:01 +0100 Subject: [PATCH] basic redirection w.o. db backend --- src/http_connection.cpp | 5 +++ src/request_handler.cpp | 79 +++++++++++++++++++++++++++++++++-------- 2 files changed, 70 insertions(+), 14 deletions(-) diff --git a/src/http_connection.cpp b/src/http_connection.cpp index ed30d2f..7741622 100644 --- a/src/http_connection.cpp +++ b/src/http_connection.cpp @@ -38,6 +38,7 @@ void HttpConnection::write() { auto self = shared_from_this(); http::async_write(socket_, response_, [self](boost::beast::error_code error_code, size_t bytes_transferred) { + cout << "Sending response:\n" << self->response_ << endl; if (!error_code) { auto error_code_socket = self->socket_.shutdown(ip::tcp::socket::shutdown_send, error_code); if (error_code_socket) { @@ -45,6 +46,10 @@ void HttpConnection::write() { } } else { cerr << "Error writing response: " << error_code.message() << endl; + auto error_code_socket = self->socket_.shutdown(ip::tcp::socket::shutdown_both, error_code); + if (error_code_socket) { + cerr << "Error shuting down socket: " << error_code_socket.message() << endl; + } } }); } \ No newline at end of file diff --git a/src/request_handler.cpp b/src/request_handler.cpp index 3bedadf..f137959 100644 --- a/src/request_handler.cpp +++ b/src/request_handler.cpp @@ -4,28 +4,79 @@ #include #include #include +#include + +http::response BadRequest(const std::string& why) { + http::response response; + response.result(http::status::bad_request); + response.set(http::field::server, "Beast"); + response.set(http::field::content_type, "text/html"); + response.body() = why; + response.prepare_payload(); + return response; +} http::response RequestHandler::handle(const http::request& request) { string_view target = request.target(); - + http::verb method = request.method(); if (target == "/") { - //case 1: "/" -> serve angular frontend or static frontend what ever - http::response response; - response.result(http::status::ok); - response.version(request.version()); - response.set(http::field::server, "Beast"); - response.set(http::field::content_type, "text/html"); - response.keep_alive(); + if(method == http::verb::get) { + //case 1: "/" -> serve angular frontend or static frontend what ever + http::response response; + response.result(http::status::ok); + response.version(request.version()); + response.set(http::field::server, "Beast"); + response.set(http::field::content_type, "text/html"); - //todo: load angular application / plain html & js - response.body() = "

TEST

"; + //todo: load angular application / plain html & js + response.body() = "

TEST

"; - response.prepare_payload(); - return response; + response.prepare_payload(); + return response; + } + else if (method == http::verb::post) { + if(request.find(http::field::content_type) == request.end()) { + return BadRequest("Content-Type header is required for POST requests"); + } + auto content_type = request[http::field::content_type]; + if(content_type != "text/plain") { + return BadRequest("Content-Type must be text/plain"); + } + std::string url = request.body(); + std::regex url_regex("^(https?://)?(?:www\\.)?[-a-zA-Z0-9@%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b(?:[-a-zA-Z0-9()@:%_\\+.~#?&/=]*)$"); + std::smatch url_match; + if(!std::regex_match(url, url_match, url_regex)) { + return BadRequest("Invalid URL"); + } + if(!url_match[1].matched){ + url = "https://" + url; + } + + //todo: save url to database and return short url + + return BadRequest("Request is actually not bad. processing " + url); + } + }else { + if(method == http::verb::get){ + http::response response; + std::string short_url = target.substr(1); + + std::string expanded_url = "https://google.com"; //todo: get expanded url from database + + response.result(http::status::moved_permanently); + response.set(http::field::location, expanded_url); + response.version(request.version()); + response.set(http::field::server, "Beast"); + response.body() = "Redirecting to " + expanded_url; + response.prepare_payload(); + return response; + } else { + return BadRequest("Method not allowed"); + } } - + //case 2: "/url" -> redirect to expanded url //case 3: neither -> redirect to 404 - return http::response{http::status::bad_request, request.version()}; + return BadRequest("No rule matched."); } \ No newline at end of file