feat(request): catch parse errors
This commit is contained in:
parent
36961fc468
commit
64f5c39fb3
@ -42,17 +42,19 @@ void Client::request()
|
||||
buffer[bytesRead] = '\0'; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
|
||||
httpRequest_->receiveData(buffer, static_cast<size_t>(bytesRead));
|
||||
|
||||
if (httpRequest_->getState() == HttpRequest::State::Complete)
|
||||
if (httpRequest_->getState() == HttpRequest::State::Complete ||
|
||||
httpRequest_->getState() == HttpRequest::State::ParseError)
|
||||
{
|
||||
Log::info("Received complete request",
|
||||
{
|
||||
Log::info("Received complete request", {
|
||||
{"request_method", httpRequest_->getMethod()},
|
||||
{"request_target", httpRequest_->getTarget()},
|
||||
{"http_version", httpRequest_->getHttpVersion()},
|
||||
{"headers", httpRequest_->getHeaders().toString()},
|
||||
{"body", httpRequest_->getBody()},
|
||||
{"state", std::to_string(static_cast<uint8_t>(httpRequest_->getState()))},
|
||||
});
|
||||
server_.responseReady(client_socket_->getFd());
|
||||
httpRequest_->reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -66,8 +68,20 @@ void Client::request()
|
||||
|
||||
std::string Client::getResponse() const
|
||||
{
|
||||
std::string response = "HTTP/1.1 200 OK\r\nContent-Length: 32\r\n\r\nHello, World!";
|
||||
Log::trace(LOCATION);
|
||||
std::string response = "HTTP/1.1 ";
|
||||
if (httpRequest_->getState() == HttpRequest::State::ParseError)
|
||||
{
|
||||
response += "400 Bad Request\r\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
response += "200 OK\r\n";
|
||||
}
|
||||
// further validation can be added here
|
||||
response += "Content-Length: 18\r\n\r\n";
|
||||
response += "Server port " + std::to_string(server_config_.getPort()) + "\r\n";
|
||||
|
||||
Log::debug("Sending response:\n" + response);
|
||||
return response;
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
|
||||
#include <webserv/config/utils.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
@ -7,11 +8,15 @@ namespace utils
|
||||
{
|
||||
size_t stoul(const std::string &str, int base)
|
||||
{
|
||||
if (str.find_first_not_of("0123456789abcdefABCDEF") != std::string::npos)
|
||||
{
|
||||
throw std::invalid_argument("Invalid number: " + str);
|
||||
}
|
||||
size_t idx = 0;
|
||||
unsigned long value = std::stoul(str, &idx, base);
|
||||
if (idx != str.length())
|
||||
{
|
||||
throw std::invalid_argument("Invalid characters in number: " + str);
|
||||
throw std::invalid_argument("Invalid number with extra characters: " + str);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -16,21 +16,8 @@ std::optional<size_t> HttpHeaders::getContentLength() const
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
if (value.find_first_not_of("0123456789") != std::string::npos)
|
||||
{
|
||||
Log::warning("Non-numeric Content-Length header value: " + value);
|
||||
return std::nullopt;
|
||||
}
|
||||
try
|
||||
{
|
||||
return utils::stoul(value);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log::warning("Invalid Content-Length header value: " + value);
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::string> HttpHeaders::getContentType() const
|
||||
{
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
#include "webserv/config/utils.hpp"
|
||||
|
||||
#include <webserv/http/HttpConstants.hpp> // for CRLF, DOUBLE_CRLF
|
||||
#include <webserv/http/HttpRequest.hpp>
|
||||
#include <webserv/log/Log.hpp> // for Log, LOCATION
|
||||
@ -46,6 +48,8 @@ void HttpRequest::receiveData(const char *data, size_t length)
|
||||
void HttpRequest::parseBuffer()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (state_)
|
||||
{
|
||||
@ -79,6 +83,13 @@ void HttpRequest::parseBuffer()
|
||||
case State::ParseError: Log::warning("Parse error occurred, stopping further processing"); return;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log::error("Exception during parsing, marking request as ParseError");
|
||||
state_ = State::ParseError;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HttpRequest::parseBufferforRequestLine()
|
||||
@ -124,10 +135,8 @@ bool HttpRequest::parseBufferforHeaders()
|
||||
Log::debug("Headers waiting for more data: " + LOCATION);
|
||||
return false; // Wait for more data
|
||||
}
|
||||
// headers_ = buffer_.substr(0, pos + Http::Protocol::CRLF.size()); // Include the last \r\n
|
||||
headers_.parse(buffer_.substr(0, pos + Http::Protocol::CRLF.size()));
|
||||
buffer_.erase(0, pos + Http::Protocol::DOUBLE_CRLF.size());
|
||||
// parseContentLength();
|
||||
|
||||
if (this->headers_.getContentLength().value_or(0) > 0)
|
||||
{
|
||||
@ -156,17 +165,9 @@ bool HttpRequest::parseBufferforChunkedBody()
|
||||
return false;
|
||||
}
|
||||
std::string chunkSizeStr = buffer_.substr(0, pos);
|
||||
size_t chunkSize = 0;
|
||||
try
|
||||
{
|
||||
chunkSize = std::stoul(chunkSizeStr, nullptr, 16);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
Log::warning("Invalid chunk size: " + chunkSizeStr + " (" + e.what() + ")");
|
||||
state_ = State::ParseError; // Mark as complete to avoid further processing
|
||||
return true;
|
||||
}
|
||||
Log::debug("Chunk size string: " + chunkSizeStr);
|
||||
size_t chunkSize = utils::stoul(chunkSizeStr, 16);
|
||||
Log::warning("Invalid chunk size: " + chunkSizeStr);
|
||||
if (chunkSize == 0)
|
||||
{
|
||||
state_ = State::Complete; // Last chunk
|
||||
|
||||
Loading…
Reference in New Issue
Block a user