feat: refactor HttpResponse and ErrorHandler for improved response handling and error management
This commit is contained in:
parent
be8c5a80b4
commit
bd01a172c5
@ -16,7 +16,7 @@
|
||||
|
||||
Client::Client(std::unique_ptr<Socket> socket, Server &server)
|
||||
: client_socket_(std::move(socket)), server_(std::ref(server)), httpRequest_(std::make_unique<HttpRequest>(this)),
|
||||
httpResponse_(std::make_unique<HttpResponse>(this))
|
||||
httpResponse_(std::make_unique<HttpResponse>())
|
||||
{
|
||||
Log::info("New client connected, fd: " + std::to_string(client_socket_->getFd()));
|
||||
}
|
||||
@ -93,26 +93,17 @@ void Client::request()
|
||||
bool Client::isResponseReady() const
|
||||
{
|
||||
// todo: poll the httpResponse_ object
|
||||
return httpResponse_->isComplete();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Client::getResponse() const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
// if (httpRequest_->getState() == HttpRequest::State::ParseError)
|
||||
// {
|
||||
// return ErrorHandler::generateErrorPage(Http::StatusCode::BAD_REQUEST);
|
||||
// }
|
||||
// std::string response = "HTTP/1.1 ";
|
||||
// response += "200 OK\r\n";
|
||||
if (httpRequest_->getState() == HttpRequest::State::ParseError)
|
||||
{
|
||||
return ErrorHandler::getErrorResponse(Http::StatusCode::BAD_REQUEST).toBytes();
|
||||
}
|
||||
|
||||
// auto serverName = server_config_->getDirectiveValue<std::string>("server_name");
|
||||
// auto port = server_config_->getDirectiveValue<int>("listen");
|
||||
// std::string body = "Server Name " + serverName + "\r\n";
|
||||
// body += "Server port " + std::to_string(port) + "\r\n";
|
||||
// response += "Content-Length: " + std::to_string(body.size()) + "\r\n\r\n";
|
||||
// response += body;
|
||||
// Log::info("Prepared response for client fd: " + std::to_string(client_socket_->getFd()));
|
||||
// Log::debug("Sending response:\n" + response);
|
||||
httpResponse_->setStatus(200);
|
||||
httpResponse_->addHeader("Content-Type", "text/plain");
|
||||
httpResponse_->appendBody("Hello, World!\n");
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
#include <cstddef> // for size_t
|
||||
#include <cstdint>
|
||||
#include <memory> // for unique_ptr
|
||||
#include <string> // for string
|
||||
#include <vector>
|
||||
|
||||
class Server;
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "webserv/http/HttpResponse.hpp"
|
||||
|
||||
#include <webserv/config/AConfig.hpp>
|
||||
|
||||
class ErrorHandler
|
||||
{
|
||||
public:
|
||||
static std::string getErrorResponse(int statusCode, AConfig *config = nullptr);
|
||||
static HttpResponse getErrorResponse(int statusCode, AConfig *config = nullptr);
|
||||
|
||||
private:
|
||||
static std::string generateErrorPage(int statusCode, AConfig *config = nullptr);
|
||||
static std::string generateErrorHeader(int statusCode, const std::string &body);
|
||||
static std::string generateDefaultErrorPage(int statusCode);
|
||||
static std::string_view getStatusMessage(int statusCode);
|
||||
// static bool isValidStatusCode(int statusCode);
|
||||
static std::string getErrorPageFile(const std::string &path);
|
||||
};
|
||||
@ -1,3 +1,5 @@
|
||||
#include "webserv/http/HttpResponse.hpp"
|
||||
|
||||
#include <webserv/config/AConfig.hpp> // for AConfig
|
||||
#include <webserv/config/ConfigManager.hpp> // for ConfigManager
|
||||
#include <webserv/config/GlobalConfig.hpp> // for GlobalConfig
|
||||
@ -5,36 +7,32 @@
|
||||
#include <webserv/http/HttpConstants.hpp> // for StatusCodeInfo, CRLF, DOUBLE_CRLF, INTERNAL_SERVER_ERROR, statusCodeInfos
|
||||
#include <webserv/log/Log.hpp> // for Log
|
||||
|
||||
#include <array> // for array
|
||||
#include <fstream> // for basic_ifstream, basic_filebuf, basic_ostream::operator<<, ifstream, stringstream
|
||||
#include <sstream> // for basic_stringstream
|
||||
#include <string> // for basic_string, operator+, allocator, char_traits, string, to_string
|
||||
#include <string_view> // for string_view
|
||||
|
||||
std::string ErrorHandler::getErrorResponse(int statusCode, AConfig *config)
|
||||
HttpResponse ErrorHandler::getErrorResponse(int statusCode, AConfig *config)
|
||||
{
|
||||
HttpResponse response;
|
||||
|
||||
std::string body = generateErrorPage(statusCode, config);
|
||||
Log::debug("Generated error page : " + generateErrorHeader(statusCode, body) + body);
|
||||
return generateErrorHeader(statusCode, body) + body;
|
||||
}
|
||||
|
||||
std::string ErrorHandler::generateErrorHeader(int statusCode, const std::string &body)
|
||||
{
|
||||
std::string response = "HTTP/1.1 ";
|
||||
response += std::to_string(statusCode) + " ";
|
||||
response += std::string(getStatusMessage(statusCode)) + std::string(Http::Protocol::CRLF);
|
||||
response += "Content-Type: text/html" + std::string(Http::Protocol::CRLF);
|
||||
response +=
|
||||
"Content-Length: " + std::to_string(body.size()) + std::string(Http::Protocol::DOUBLE_CRLF); // End of headers
|
||||
response.appendBody(body);
|
||||
response.setStatus(statusCode);
|
||||
response.addHeader("Content-Type", "text/html");
|
||||
response.addHeader("Connection", "close");
|
||||
return response;
|
||||
}
|
||||
|
||||
std::string ErrorHandler::generateErrorPage(int statusCode, AConfig *config)
|
||||
{
|
||||
|
||||
if (config != nullptr)
|
||||
Log::trace(LOCATION);
|
||||
if (config == nullptr)
|
||||
{
|
||||
config = ConfigManager::getInstance().getGlobalConfig();
|
||||
Log::debug("Using global config for error page generation");
|
||||
}
|
||||
if (config != nullptr)
|
||||
{
|
||||
Log::info("Checking for custom error page for status code: " + std::to_string(statusCode));
|
||||
std::string customPage = config->getErrorPage(statusCode);
|
||||
if (!customPage.empty())
|
||||
@ -49,24 +47,11 @@ std::string ErrorHandler::generateErrorPage(int statusCode, AConfig *config)
|
||||
std::string ErrorHandler::generateDefaultErrorPage(int statusCode)
|
||||
{
|
||||
Log::info("Generating default error page for status code: " + std::to_string(statusCode));
|
||||
|
||||
std::string_view statusMessage = getStatusMessage(statusCode);
|
||||
std::string html = "<html><head><title>" + std::to_string(statusCode) + " " + std::string(statusMessage) +
|
||||
"</title></head><body><h1>" + std::to_string(statusCode) + " " + std::string(statusMessage) +
|
||||
std::string statusMessage = Http::getStatusCodeReason(statusCode);
|
||||
std::string html = "<html><head><title>" + std::to_string(statusCode) + " " + statusMessage +
|
||||
"</title></head><body><h1>" + std::to_string(statusCode) + " " + statusMessage +
|
||||
"</h1><hr><p>webserv</p></body></html>";
|
||||
return generateErrorHeader(statusCode, html) + html;
|
||||
}
|
||||
|
||||
std::string_view ErrorHandler::getStatusMessage(int statusCode)
|
||||
{
|
||||
for (const auto info : Http::statusCodeInfos)
|
||||
{
|
||||
if (info.code == statusCode)
|
||||
{
|
||||
return info.reason;
|
||||
}
|
||||
}
|
||||
return "Unknown Status";
|
||||
return html;
|
||||
}
|
||||
|
||||
std::string ErrorHandler::getErrorPageFile(const std::string &path)
|
||||
|
||||
@ -18,15 +18,6 @@
|
||||
class HttpHeaders
|
||||
{
|
||||
public:
|
||||
HttpHeaders() = default;
|
||||
|
||||
HttpHeaders(const HttpHeaders &other) = delete;
|
||||
HttpHeaders(HttpHeaders &&other) noexcept = delete;
|
||||
HttpHeaders &operator=(const HttpHeaders &other) = delete;
|
||||
HttpHeaders &operator=(HttpHeaders &&other) noexcept = delete;
|
||||
|
||||
~HttpHeaders() = default;
|
||||
|
||||
const std::string &get(const std::string &name) const;
|
||||
bool has(const std::string &name) const;
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
HttpResponse::HttpResponse(Client *client) : client_(client), headers_(std::make_unique<HttpHeaders>()) {}
|
||||
HttpResponse::HttpResponse() : headers_(std::make_unique<HttpHeaders>()) {}
|
||||
|
||||
void HttpResponse::addHeader(const std::string &key, const std::string &value)
|
||||
{
|
||||
@ -22,11 +22,33 @@ void HttpResponse::appendBody(const std::string &body)
|
||||
body_.insert(body_.end(), body.begin(), body.end());
|
||||
}
|
||||
|
||||
void HttpResponse::setBody(const std::vector<uint8_t> &data)
|
||||
{
|
||||
body_ = data;
|
||||
setComplete();
|
||||
}
|
||||
|
||||
void HttpResponse::setBody(const std::string &body)
|
||||
{
|
||||
body_.assign(body.begin(), body.end());
|
||||
setComplete();
|
||||
}
|
||||
|
||||
void HttpResponse::setStatus(int statusCode)
|
||||
{
|
||||
statusCode_ = statusCode;
|
||||
}
|
||||
|
||||
void HttpResponse::setComplete()
|
||||
{
|
||||
complete_ = true;
|
||||
}
|
||||
|
||||
bool HttpResponse::isComplete() const
|
||||
{
|
||||
return complete_;
|
||||
}
|
||||
|
||||
const HttpHeaders &HttpResponse::getHeaders() const
|
||||
{
|
||||
return *headers_;
|
||||
|
||||
@ -12,12 +12,12 @@ class Client;
|
||||
class HttpResponse
|
||||
{
|
||||
public:
|
||||
HttpResponse(Client *client);
|
||||
HttpResponse();
|
||||
|
||||
HttpResponse(const HttpResponse &other) = delete; // Disable copy constructor
|
||||
HttpResponse &operator=(const HttpResponse &other) = delete; // Disable copy assignment
|
||||
HttpResponse(HttpResponse &&other) noexcept = delete; // Move constructor
|
||||
HttpResponse &operator=(HttpResponse &&other) noexcept = delete; // Move assignment
|
||||
HttpResponse(HttpResponse &&other) noexcept = default; // Move constructor
|
||||
HttpResponse &operator=(HttpResponse &&other) noexcept = default; // Move assignment
|
||||
|
||||
~HttpResponse() = default;
|
||||
|
||||
@ -26,6 +26,9 @@ class HttpResponse
|
||||
void appendBody(const std::vector<uint8_t> &data);
|
||||
void appendBody(const std::string &body);
|
||||
|
||||
void setBody(const std::vector<uint8_t> &data);
|
||||
void setBody(const std::string &body);
|
||||
|
||||
void setComplete();
|
||||
|
||||
void setStatus(int statusCode);
|
||||
@ -40,7 +43,6 @@ class HttpResponse
|
||||
[[nodiscard]] std::string getStatusLine() const;
|
||||
[[nodiscard]] std::string getContentLength() const;
|
||||
|
||||
Client *client_;
|
||||
std::vector<uint8_t> body_;
|
||||
std::unique_ptr<HttpHeaders> headers_;
|
||||
bool complete_ = false;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user