6#include "../includes/Request.hpp"
13 std::string
trim(
const std::string& s)
16 int end =
static_cast<int>(s.size()) - 1;
17 while (start <= end && std::isspace(
static_cast<unsigned char>(s[start]))) {
20 while (end >= start && std::isspace(
static_cast<unsigned char>(s[end]))) {
26 return s.substr(start, end - start + 1);
31 unsigned long hostOrder = ntohl(addr.sin_addr.s_addr);
32 std::ostringstream oss;
33 oss << ((hostOrder >> 24) & 0xFF) <<
"."
34 << ((hostOrder >> 16) & 0xFF) <<
"."
35 << ((hostOrder >> 8) & 0xFF) <<
"."
36 << (hostOrder & 0xFF);
42Request::Request(): _methodName(
UNKNOWN_METHOD), _contentLength(-1), _reqState(
REQ_HEADERS), _statusCode(
"200"), _maxBodySize(0), _totalBytesRead(0), _chunkSize(0), _chunkDecodeOffset(0), _isBodyProcessed(false), _ramParsePos(0)
45Request::Request(
long long maxBodySize): _methodName(
UNKNOWN_METHOD), _contentLength(-1), _reqState(
REQ_HEADERS), _statusCode(
"200"), _maxBodySize(static_cast<size_t>(maxBodySize)), _totalBytesRead(0), _chunkSize(0), _chunkDecodeOffset(0), _isBodyProcessed(false), _ramParsePos(0)
48Request::Request(
const Request& other): _methodName(other._methodName), _URL(other._URL), _protocol(other._protocol), _query(other._query), _contentLength(other._contentLength), _body(other._body), _decodedBody(other._decodedBody), _headers(other._headers), _cookies(other._cookies), _reqState(other._reqState), _statusCode(other._statusCode), _maxBodySize(other._maxBodySize), _totalBytesRead(other._totalBytesRead), _chunkSize(other._chunkSize), _chunkDecodeOffset(other._chunkDecodeOffset), _isBodyProcessed(other._isBodyProcessed), _chunkBuffer(other._chunkBuffer), _ramParsePos(other._ramParsePos)
109 size_t firstSpace = line.find(
' ');
110 if (firstSpace == std::string::npos)
116 std::string methodStr = line.substr(0, firstSpace);
124 size_t secondSpace = line.find(
' ', firstSpace + 1);
125 if (secondSpace == std::string::npos)
128 _URL = line.substr(firstSpace + 1);
140 _URL = line.substr(firstSpace + 1, secondSpace - firstSpace - 1);
141 _protocol = line.substr(secondSpace + 1);
159 size_t queryPos =
_URL.find(
'?');
161 if (queryPos != std::string::npos)
170 size_t headerEnd = rawBuffer.find(
"\r\n\r\n");
171 if (headerEnd == std::string::npos)
175 std::string headerSection = rawBuffer.substr(0, headerEnd);
176 size_t lineStart = 0;
177 bool firstLine =
true;
179 while (lineStart < headerSection.size())
181 size_t lineEnd = headerSection.find(
"\r\n", lineStart);
182 if (lineEnd == std::string::npos)
183 lineEnd = headerSection.size();
185 std::string line = headerSection.substr(lineStart, lineEnd - lineStart);
196 lineStart = lineEnd + 2;
202 return headerEnd + 4;
208 while (pos < cookieHeader.size())
210 size_t semicolonPos = cookieHeader.find(
';', pos);
211 if (semicolonPos == std::string::npos)
212 semicolonPos = cookieHeader.size();
214 std::string token =
req_utils::trim(cookieHeader.substr(pos, semicolonPos - pos));
215 size_t eqPos = token.find(
'=');
216 if (eqPos != std::string::npos)
223 pos = semicolonPos + 1;
230 std::string transferEncoding =
getHeader(
"Transfer-Encoding");
231 std::string contentLengthStr =
getHeader(
"Content-Length");
233 std::string toLower = transferEncoding;
234 for (
size_t i = 0; i < toLower.size(); ++i)
235 toLower[i] = std::tolower(
static_cast<unsigned char>(toLower[i]));
236 if (toLower.find(
"chunked") != std::string::npos)
241 else if (!contentLengthStr.empty())
244 long long cl = strtoll(contentLengthStr.c_str(), &endPtr, 10);
245 if (*endPtr !=
'\0' || cl < 0)
269 std::string keyCopy = key;
270 for (
size_t i = 0; i < key.size(); ++i)
272 keyCopy[i] = std::tolower(
static_cast<unsigned char>(keyCopy[i]));
275 return _headers.find(keyCopy)->second;
281 std::map<std::string, std::string>::const_iterator it =
_cookies.find(key);
289 size_t colonPos = line.find(
':');
290 if (colonPos == std::string::npos)
296 for (
size_t i = 0; i < key.size(); ++i)
297 key[i] = std::tolower(
static_cast<unsigned char>(key[i]));
308 size_t ReadBaytes =
_body.
read(&tempBuffer[0], tempBuffer.size());
310 _chunkBuffer += std::string(&tempBuffer[0], ReadBaytes);
314 if (crlfPos == std::string::npos)
317 size_t semi = hexStr.find(
';');
318 if (semi != std::string::npos)
319 hexStr = hexStr.substr(0, semi);
321 unsigned long chunkSize = strtoul(hexStr.c_str(), NULL, 16);
322 size_t totalBytesNeeded = crlfPos + 2 + chunkSize + 2;
326 if (
_chunkBuffer.substr(crlfPos + 2 + chunkSize, 2) !=
"\r\n") {
331 if (chunkSize == 0) {
350 std::stringstream ss;
352 std::string str = ss.str();
361 return newData.find(
"0\r\n\r\n") != std::string::npos;
HTTPMethod
Represents the HTTP methods supported by the server as a bitmask.
ReqState
Represents the current network-reading phase of the HTTP request.
static HTTPMethod stringToMethod(const std::string &methodStr)
Converts a string representation of an HTTP method to its enum value.
size_t getSize() const
Gets total bytes currently stored (whether in RAM or File).
void append(const char *data, size_t length)
Appends raw byte data to the store. Automatically transitions from RAM to FILE_MODE if _bufferLimit i...
void resetReadPosition()
Resets the internal read position to the beginning of the data.
size_t read(char *buffer, size_t length)
Reads data from the store starting at the current read position. Advances the internal read position ...
void clear()
Resets the store, clears the vector, and closes the temp file descriptor.
size_t _chunkDecodeOffset
bool isChunkedDone(const std::string &newData) const
Checks if the incoming chunked data contains the terminal "\r\n\r\n". Used to transition from REQ_CHU...
DataStore & getBodyStore()
Returns a reference to the DataStore to allow direct writing from recv().
const std::string & getQuery() const
void _parseRequestLine(const std::string &line)
void _parseHeaderLine(const std::string &line)
HTTPMethod getMethod() const
std::string getHeader(const std::string &key) const
Gets a specific header value.
ReqState getReqState() const
std::string getStatusCode() const
size_t parseHeaders(const std::string &rawBuffer)
Parses the raw buffer containing the HTTP Request-Line and Headers. Transitions state to REQ_BODY,...
void _extractQueryFromURL()
long long getContentLength() const
void _parseCookies(const std::string &cookieHeader)
size_t getMaxBytesToRead() const
const std::string & getURL() const
std::map< std::string, std::string > _headers
const std::map< std::string, std::string > & getHeaders() const
Request & operator=(const Request &other)
const std::map< std::string, std::string > & getCookies() const
std::string getCookie(const std::string &key) const
Gets a specific cookie value.
size_t getTotalBytesRead() const
bool processBodySlice()
Unified method to prepare the body for the Response/CGI phase. For Content-Length bodies,...
std::map< std::string, std::string > _cookies
const std::string & getProtocol() const
std::string ipv4ToString(const struct ::sockaddr_in &addr)
std::string trim(const std::string &s)