Implemented the recieving part of HttpRequest
and changed client to use HttpRequest
This commit is contained in:
parent
6766bd8744
commit
3dc12fab9d
@ -6,8 +6,10 @@
|
||||
#include <iostream>
|
||||
|
||||
Client::Client(std::unique_ptr<Socket> socket, Server &server, const ServerConfig &server_config)
|
||||
: client_socket_(std::move(socket)), server_(std::ref(server)), server_config_(std::cref(server_config))
|
||||
: client_socket_(std::move(socket)), server_(std::ref(server)), server_config_(std::cref(server_config)),
|
||||
httpRequest_(std::make_unique<HttpRequest>(&server_config, this))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Client::~Client()
|
||||
@ -16,23 +18,6 @@ Client::~Client()
|
||||
server_.removeFromEpoll(*client_socket_);
|
||||
};
|
||||
|
||||
int Client::parseHeaderforContentLength(const std::string &request) // NOLINT
|
||||
{
|
||||
std::string header = "Content-Length: ";
|
||||
size_t pos = request.find(header);
|
||||
Log::debug("Parsing header for Content-Length...\n" + header);
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
size_t start = pos + header.length();
|
||||
size_t end = request.find("\r\n", start);
|
||||
if (end != std::string::npos)
|
||||
{
|
||||
std::string lengthStr = request.substr(start, end - start);
|
||||
return std::atoi(lengthStr.c_str());
|
||||
}
|
||||
}
|
||||
return -1; // Not found
|
||||
}
|
||||
|
||||
void Client::request()
|
||||
{
|
||||
@ -51,33 +36,15 @@ void Client::request()
|
||||
}
|
||||
|
||||
buffer[bytesRead] = '\0'; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
|
||||
requestBuffer_ += buffer; // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
|
||||
if (header_.empty())
|
||||
{
|
||||
auto headerEnd = requestBuffer_.find("\r\n\r\n");
|
||||
if (headerEnd != std::string::npos)
|
||||
{
|
||||
header_ = requestBuffer_.substr(0, headerEnd + 4);
|
||||
contentLength_ = parseHeaderforContentLength(header_);
|
||||
if (contentLength_ == -1)
|
||||
{
|
||||
Log::info("Received complete request:\n" + requestBuffer_ + "\n=== HEADER FINISHED\n");
|
||||
server_.responseReady(client_socket_->getFd());
|
||||
}
|
||||
requestBuffer_.erase(0, headerEnd + 4);
|
||||
return;
|
||||
}
|
||||
httpRequest_->receiveData(buffer, static_cast<size_t>(bytesRead));
|
||||
|
||||
if(httpRequest_->getState() == HttpRequest::State::Complete) {
|
||||
Log::info("Received complete request:\n" + httpRequest_->getHeaders() + httpRequest_->getBody() + "\n=== FULL REQUEST FINISHED\n");
|
||||
server_.responseReady(client_socket_->getFd());
|
||||
httpRequest_->reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
content_ += requestBuffer_;
|
||||
if (content_.size() >= contentLength_)
|
||||
{
|
||||
Log::info("Received complete request:\n" + header_ + content_ + "\n=== FULL REQUEST FINISHED\n");
|
||||
server_.responseReady(client_socket_->getFd());
|
||||
requestBuffer_.clear();
|
||||
contentLength_ = -1;
|
||||
}
|
||||
else {
|
||||
Log::debug("Received partial request:\n" + httpRequest_->getHeaders() + httpRequest_->getBody() + "\n=== PARTIAL REQUEST\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
#include <webserv/config/ServerConfig.hpp>
|
||||
#include <webserv/server/Server.hpp>
|
||||
|
||||
#include <webserv/http/HttpRequest.hpp>
|
||||
#include <memory>
|
||||
|
||||
class Server;
|
||||
@ -25,11 +25,12 @@ class Client
|
||||
[[nodiscard]] std::string getResponse() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<HttpRequest> httpRequest_ = nullptr;
|
||||
int parseHeaderforContentLength(const std::string &request);
|
||||
int contentLength_{-1};
|
||||
std::string requestBuffer_;
|
||||
std::string header_;
|
||||
std::string content_;
|
||||
// int contentLength_{-1};
|
||||
// std::string requestBuffer_;
|
||||
// std::string header_;
|
||||
// std::string content_;
|
||||
std::unique_ptr<Socket> client_socket_;
|
||||
const Server &server_;
|
||||
const ServerConfig &server_config_;
|
||||
|
||||
@ -1,5 +1,130 @@
|
||||
#include <webserv/http/HttpRequest.hpp>
|
||||
#include <webserv/log/Log.hpp>
|
||||
|
||||
HttpRequest::HttpRequest()
|
||||
HttpRequest::HttpRequest(const ServerConfig *serverConfig, const Client *client)
|
||||
: serverConfig_(serverConfig), client_(client)
|
||||
{
|
||||
Log::trace("HttpRequest constructor called");
|
||||
}
|
||||
HttpRequest::~HttpRequest()
|
||||
{
|
||||
Log::trace("HttpRequest destructor called");
|
||||
}
|
||||
|
||||
HttpRequest::State HttpRequest::getState() const
|
||||
{
|
||||
Log::trace("HttpRequest::getState() called");
|
||||
return state_;
|
||||
}
|
||||
|
||||
const std::string &HttpRequest::getHeaders() const
|
||||
{
|
||||
return headers_;
|
||||
}
|
||||
|
||||
const std::string &HttpRequest::getBody() const
|
||||
{
|
||||
return body_;
|
||||
}
|
||||
|
||||
size_t HttpRequest::getContentLength() const
|
||||
{
|
||||
return contentLength_;
|
||||
}
|
||||
|
||||
void HttpRequest::receiveData(const char *data, size_t length)
|
||||
{
|
||||
Log::trace("HttpRequest::receiveData() called");
|
||||
buffer_.append(data, length);
|
||||
parseBuffer();
|
||||
}
|
||||
|
||||
void HttpRequest::parseContentLength()
|
||||
{
|
||||
// Parse headers to find Content-Length
|
||||
size_t pos = headers_.find("Content-Length:");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
pos += 15;
|
||||
while (pos < headers_.size() && (headers_[pos] == ' ' || headers_[pos] == '\t'))
|
||||
{
|
||||
++pos; // Skip whitespace
|
||||
}
|
||||
size_t endPos = headers_.find("\r\n", pos);
|
||||
std::string contentLengthValue = headers_.substr(pos, endPos - pos);
|
||||
contentLength_ = std::stoul(contentLengthValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
contentLength_ = 0; // No body expected
|
||||
}
|
||||
}
|
||||
|
||||
void HttpRequest::parseBuffer()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (state_ == State::RequestLine)
|
||||
{
|
||||
size_t pos = buffer_.find("\r\n");
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
Log::debug("HttpRequest::parseBuffer() in state RequestLine waiting for more data");
|
||||
return; // Wait for more data
|
||||
}
|
||||
requestLine_ = buffer_.substr(0, pos);
|
||||
buffer_.erase(0, pos + 2);
|
||||
state_ = State::Headers;
|
||||
}
|
||||
else if (state_ == State::Headers)
|
||||
{
|
||||
size_t pos = buffer_.find("\r\n\r\n");
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
Log::debug("HttpRequest::parseBuffer() in state Headers waiting for more data");
|
||||
return; // Wait for more data
|
||||
}
|
||||
headers_ = buffer_.substr(0, pos + 2); // Include the last \r\n
|
||||
buffer_.erase(0, pos + 4);
|
||||
parseContentLength();
|
||||
|
||||
if (contentLength_ > 0)
|
||||
{
|
||||
state_ = State::Body;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::debug("HttpRequest::parseBuffer() in state Headers no body to read");
|
||||
state_ = State::Complete;
|
||||
return; // No body to read
|
||||
}
|
||||
}
|
||||
else if (state_ == State::Body)
|
||||
{
|
||||
if (buffer_.size() < contentLength_)
|
||||
{
|
||||
Log::debug("HttpRequest::parseBuffer() in state Body waiting for more data");
|
||||
return; // Wait for more data
|
||||
}
|
||||
body_ = buffer_.substr(0, contentLength_);
|
||||
buffer_.erase(0, contentLength_);
|
||||
state_ = State::Complete;
|
||||
}
|
||||
else if (state_ == State::Complete)
|
||||
{
|
||||
Log::debug("HttpRequest::parseBuffer() request is complete");
|
||||
return; // Request is complete
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HttpRequest::reset()
|
||||
{
|
||||
Log::trace("HttpRequest::reset() called");
|
||||
state_ = State::RequestLine;
|
||||
buffer_.clear();
|
||||
requestLine_.clear();
|
||||
headers_.clear();
|
||||
body_.clear();
|
||||
contentLength_ = 0;
|
||||
}
|
||||
|
||||
@ -1,7 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "webserv/config/ServerConfig.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class Client;
|
||||
class HttpRequest
|
||||
{
|
||||
public:
|
||||
HttpRequest();
|
||||
enum class State : std::uint8_t
|
||||
{
|
||||
RequestLine,
|
||||
Headers,
|
||||
Body,
|
||||
Complete
|
||||
};
|
||||
|
||||
HttpRequest(const ServerConfig *serverConfig, const Client *client);
|
||||
|
||||
HttpRequest(const HttpRequest &other) = delete;
|
||||
HttpRequest(HttpRequest &&other) noexcept = delete;
|
||||
HttpRequest &operator=(const HttpRequest &other) = delete;
|
||||
HttpRequest &operator=(HttpRequest &&other) noexcept = delete;
|
||||
~HttpRequest();
|
||||
|
||||
[[nodiscard]] State getState() const;
|
||||
[[nodiscard]] const std::string &getHeaders() const;
|
||||
[[nodiscard]] const std::string &getBody() const;
|
||||
[[nodiscard]] size_t getContentLength() const;
|
||||
|
||||
void receiveData(const char *data, size_t length);
|
||||
void reset();
|
||||
|
||||
private:
|
||||
void parseBuffer();
|
||||
void parseContentLength();
|
||||
const ServerConfig *serverConfig_;
|
||||
const Client *client_;
|
||||
|
||||
State state_ = State::RequestLine;
|
||||
|
||||
std::string buffer_;
|
||||
|
||||
std::string requestLine_;
|
||||
std::string headers_;
|
||||
std::string body_;
|
||||
size_t contentLength_ = 0;
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user