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>
|
#include <iostream>
|
||||||
|
|
||||||
Client::Client(std::unique_ptr<Socket> socket, Server &server, const ServerConfig &server_config)
|
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()
|
Client::~Client()
|
||||||
@ -16,23 +18,6 @@ Client::~Client()
|
|||||||
server_.removeFromEpoll(*client_socket_);
|
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()
|
void Client::request()
|
||||||
{
|
{
|
||||||
@ -51,33 +36,15 @@ void Client::request()
|
|||||||
}
|
}
|
||||||
|
|
||||||
buffer[bytesRead] = '\0'; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
|
buffer[bytesRead] = '\0'; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
|
||||||
requestBuffer_ += buffer; // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
|
httpRequest_->receiveData(buffer, static_cast<size_t>(bytesRead));
|
||||||
if (header_.empty())
|
|
||||||
{
|
if(httpRequest_->getState() == HttpRequest::State::Complete) {
|
||||||
auto headerEnd = requestBuffer_.find("\r\n\r\n");
|
Log::info("Received complete request:\n" + httpRequest_->getHeaders() + httpRequest_->getBody() + "\n=== FULL REQUEST FINISHED\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());
|
server_.responseReady(client_socket_->getFd());
|
||||||
|
httpRequest_->reset();
|
||||||
}
|
}
|
||||||
requestBuffer_.erase(0, headerEnd + 4);
|
else {
|
||||||
return;
|
Log::debug("Received partial request:\n" + httpRequest_->getHeaders() + httpRequest_->getBody() + "\n=== PARTIAL REQUEST\n");
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <webserv/config/ServerConfig.hpp>
|
#include <webserv/config/ServerConfig.hpp>
|
||||||
#include <webserv/server/Server.hpp>
|
#include <webserv/server/Server.hpp>
|
||||||
|
#include <webserv/http/HttpRequest.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class Server;
|
class Server;
|
||||||
@ -25,11 +25,12 @@ class Client
|
|||||||
[[nodiscard]] std::string getResponse() const;
|
[[nodiscard]] std::string getResponse() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::unique_ptr<HttpRequest> httpRequest_ = nullptr;
|
||||||
int parseHeaderforContentLength(const std::string &request);
|
int parseHeaderforContentLength(const std::string &request);
|
||||||
int contentLength_{-1};
|
// int contentLength_{-1};
|
||||||
std::string requestBuffer_;
|
// std::string requestBuffer_;
|
||||||
std::string header_;
|
// std::string header_;
|
||||||
std::string content_;
|
// std::string content_;
|
||||||
std::unique_ptr<Socket> client_socket_;
|
std::unique_ptr<Socket> client_socket_;
|
||||||
const Server &server_;
|
const Server &server_;
|
||||||
const ServerConfig &server_config_;
|
const ServerConfig &server_config_;
|
||||||
|
|||||||
@ -1,5 +1,130 @@
|
|||||||
#include <webserv/http/HttpRequest.hpp>
|
#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
|
#pragma once
|
||||||
|
|
||||||
|
#include "webserv/config/ServerConfig.hpp"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Client;
|
||||||
class HttpRequest
|
class HttpRequest
|
||||||
{
|
{
|
||||||
public:
|
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