Skip to content

Commit

Permalink
Merge branch 'dtolmaco/fix-build-response' into slombard/web-276-buil…
Browse files Browse the repository at this point in the history
…d-a-fully-fledged-php-website
  • Loading branch information
552020 committed May 17, 2024
2 parents 757635c + 2def820 commit 3847e1d
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 117 deletions.
252 changes: 141 additions & 111 deletions src/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,16 @@ void Server::readFromClient(Connection &conn, size_t &i, Parser &parser, HTTPReq
return;
}
}

if (!parser.getHeadersComplete())
{
Debug::log("Headers incomplete yet, exiting readFromClient.", Debug::NORMAL);
return;
}

if (parser.getHeadersComplete() && !parser.getHeadersAreParsed())
parser.parseRequestLineAndHeaders(parser.getHeadersBuffer().c_str(), request, response);

if (response.getStatusCode() != 0)
{
conn.setCanBeClosed(false);
Expand All @@ -130,76 +133,84 @@ void Server::readFromClient(Connection &conn, size_t &i, Parser &parser, HTTPReq
Debug::log("Error parsing headers or request line", Debug::OCF);
return;
}
std::cout << parser.getHeadersComplete() << " ," << request.getMethod() << std::endl;

if (parser.getHeadersComplete() && request.getMethod() == "GET")
conn.setHasFinishedReading(true);

if (response.getStatusCode() != 0)
Debug::log(toString(response.getStatusCode()), Debug::NORMAL);
if (request.getMethod() == "GET")

if (request.getMethod() == "GET" || request.getMethod() == "DELETE" \
|| request.getMethod() == "SALAD")
Debug::log("GET request, no body to read", Debug::NORMAL);
else
handlePostRequest(conn, parser, request, response);
}

void Server::handlePostRequest(Connection &conn, Parser &parser, HTTPRequest &request, HTTPResponse &response)
{
if (parser.getIsChunked() && !conn.getHasReadSocket())
{
if (parser.getIsChunked() && !conn.getHasReadSocket())
{
Debug::log("Chunked body", Debug::NORMAL);
if (!conn.readChunkedBody(parser))
{
// Case of error while reading chunked body
Debug::log("Error reading chunked body", Debug::OCF);
conn.setCanBeClosed(true);
conn.setHasFinishedReading(true);
// It could be that we had data that could be sent even if we have an error cause previous data was read
return;
}
conn.setHasReadSocket(true);
}
else if (!conn.getHasReadSocket())
Debug::log("Chunked body", Debug::NORMAL);
// TODO: double check this condition, logic
if (!conn.readChunkedBody(parser))
{
Debug::log("\033[1;33mReading body\033[0m", Debug::NORMAL);
// TODO: add comments
if (!parser.getBodyComplete() && parser.getBuffer().size() == request.getContentLength())
{
// TODO: in the new design we will return here and go to the function where the response is
parser.setBodyComplete(true);
conn.setHasFinishedReading(true);
conn.setHasDataToSend(true);
}
else if (!conn.getHasReadSocket() && !conn.readBody(parser, request, response, _config))
{
Debug::log("Error reading body", Debug::OCF);
conn.setCanBeClosed(false);
conn.setHasFinishedReading(true);
conn.setHasDataToSend(false);
return;
}
}
if (!parser.getBodyComplete() && request.getContentLength() != 0 &&
parser.getBuffer().size() == request.getContentLength())
{
// TODO: in the new design we will return here and go to the function where the response is
parser.setBodyComplete(true);
Debug::log("Error reading chunked body", Debug::OCF);
conn.setCanBeClosed(true);
conn.setHasFinishedReading(true);
conn.setCanBeClosed(false);
conn.setHasDataToSend(false);
// It could be that we had data that could be sent even if we have an error cause previous data was read
return;
}
if (!parser.getBodyComplete())
//-----------------------------//
conn.setHasReadSocket(true);
}
else if (!conn.getHasReadSocket())
{
Debug::log("\033[1;33mReading body\033[0m", Debug::NORMAL);
// TODO: double check this condition, logic
if (!parser.getBodyComplete() && parser.getBuffer().size() == request.getContentLength())
{
Debug::log("Body still incomplete, exiting readFromClient.", Debug::NORMAL);
conn.setHasFinishedReading(false);
conn.setHasReadSocket(true);
return;
parser.setBodyComplete(true);
conn.setHasFinishedReading(true);
conn.setHasDataToSend(true);
}
// std::cout << parser.getBuffer() << std::endl;
if (!request.getUploadBoundary().empty())
parser.parseFileUpload(parser.getBuffer(), request, response);
else if (request.getMethod() != "GET")
//-----------------------------//

else if (!conn.readBody(parser, request, response, _config))
{
request.setBody(parser.getBuffer());
Debug::log("Error reading body", Debug::OCF);
conn.setCanBeClosed(false);
conn.setHasFinishedReading(true);
conn.setHasDataToSend(false);
return;
}
}
// TODO: double check this condition, logic
if (!parser.getBodyComplete() && request.getContentLength() != 0 &&
parser.getBuffer().size() == request.getContentLength())
{
// TODO: in the new design we will return here and go to the function where the response is
parser.setBodyComplete(true);
conn.setHasFinishedReading(true);
conn.setCanBeClosed(false);
conn.setHasDataToSend(false);
return;
}
//-----------------------------//

if (!parser.getBodyComplete())
{
Debug::log("Body still incomplete, exiting readFromClient.", Debug::NORMAL);
conn.setHasFinishedReading(false);
conn.setHasReadSocket(true);
return;
}

if (!request.getUploadBoundary().empty())
parser.parseFileUpload(parser.getBuffer(), request, response);

request.setBody(parser.getBuffer());
conn.setHasFinishedReading(true);
}

void Server::buildResponse(Connection &conn, size_t &i, HTTPRequest &request, HTTPResponse &response)
Expand All @@ -210,77 +221,24 @@ void Server::buildResponse(Connection &conn, size_t &i, HTTPRequest &request, HT

ServerBlock serverBlock;
Directives directive;
std::string serverName;

std::cout << GREEN << "Number of server blocks: " << _config.getServerBlocks().size() << RESET << std::endl;
std::cout << "Request host: " << request.getSingleHeader("host").second << std::endl;
std::cout << "Request target: " << request.getRequestTarget() << std::endl;

std::string requestTarget = request.getRequestTarget();
// if there is "?" in the request target, we need to remove it
if (std::find(requestTarget.begin(), requestTarget.end(), '?') != requestTarget.end())
requestTarget = requestTarget.substr(0, requestTarget.find("?"));
std::cout << "Request target: " << requestTarget << std::endl;
formRequestTarget(request);

for (size_t i = 0; i < _config.getServerBlocks().size(); i++)
{
// loop through all server names in the server block
for (size_t j = 0; j < _config.getServerBlocks()[i].getServerName().size(); j++)
if (findServerName(request, _config.getServerBlocks()[i]) == request.getSingleHeader("host").second)
{
serverName = _config.getServerBlocks()[i].getServerName()[j];
std::cout << RED << "Checking server name: " << serverName << RESET << std::endl;
if (serverName == request.getSingleHeader("host").second)
{
std::cout << GREEN << "Server name found" << RESET << std::endl;
break;
}
}
if (serverName == request.getSingleHeader("host").second)
{
// _config.setServerBlockIndex(i);
serverBlock = _config.getServerBlocks()[i];
directive = serverBlock.getDirectives();
std::cout << "Request target in block: " << request.getRequestTarget() << std::endl;

for (size_t i = 0; i < serverBlock.getLocations().size(); i++)
{
std::cout << "Location: " << serverBlock.getLocations()[i]._path << " == " << request.getRequestTarget()
<< std::endl;
if (request.getRequestTarget() == serverBlock.getLocations()[i]._path)
{
std::cout << "Location found" << std::endl;
directive = serverBlock.getLocations()[i];
break;
}
}
findLocationBlock(request, _config.getServerBlocks()[i], directive);
break;
}
else if (i == _config.getServerBlocks().size() - 1)
{
static StaticContentHandler staticContentInstance;
// if error already occurred, we don't want to overwrite it
if (response.getStatusCode() != 0)
{
Debug::log("Error response" + toString(response.getStatusCode()), Debug::NORMAL);
response.setErrorResponse(response.getStatusCode());
conn.setHasDataToSend(true);
return;
}
// if no server name is found, use the default server block
staticContentInstance.handleNotFound(response);
response.setStatusCode(404, "No server block is matching the request host");
conn.setHasDataToSend(true);
Debug::log("Exiting buildResponse", Debug::NORMAL);
return;
}
std::cout << "Index: " << i << std::endl;
return (handleServerBlockError(conn, response));
}

std::string root = serverBlock.getRoot();

std::cout << "Root: " << root << std::endl;
if (root[root.size() - 1] != '/')
root = root + "/";
std::cout << RED << "Root: " << root << RESET << std::endl;
std::cout << RED << "Root: " << directive._root << RESET << std::endl;

Router router(directive);

Expand Down Expand Up @@ -771,3 +729,75 @@ void Server::printServerSockets() const
std::cout << *it << std::endl;
}
}

void Server::formRequestTarget(HTTPRequest &request)
{
std::string requestTarget = request.getRequestTarget();

// if there is "?" in the request target, we need to remove it
if (std::find(requestTarget.begin(), requestTarget.end(), '?') != requestTarget.end())
requestTarget = (requestTarget.substr(0, requestTarget.find("?")));

// if there is "http://" in the request target, we need to remove it
size_t http = requestTarget.find("http://");
if (http != std::string::npos)
{
std::string remove = "http://";
requestTarget.erase(http, remove.length());
}
request.setRequestTarget(requestTarget);
std::cout << "Request target: " << request.getRequestTarget() << std::endl;
}

void Server::findLocationBlock(HTTPRequest &request, ServerBlock& serverBlock, Directives &directive)
{
directive = serverBlock.getDirectives();

for (size_t i = 0; i < serverBlock.getLocations().size(); i++)
{
std::cout << "Location: " << serverBlock.getLocations()[i]._path << " == " << request.getRequestTarget()
<< std::endl;
if (request.getRequestTarget() == serverBlock.getLocations()[i]._path)
{
std::cout << "Location found" << std::endl;
directive = serverBlock.getLocations()[i];
break;
}
}
}

void Server::handleServerBlockError(Connection& conn, HTTPResponse &response)
{
// if error already occurred, we don't want to overwrite it
if (response.getStatusCode() != 0)
{
Debug::log("Error response" + toString(response.getStatusCode()), Debug::NORMAL);
response.setErrorResponse(response.getStatusCode());
conn.setHasDataToSend(true);
return;
}

static StaticContentHandler staticContentInstance;

staticContentInstance.handleNotFound(response);
response.setStatusCode(404, "No server block is matching the request host");
conn.setHasDataToSend(true);
return;
}

std::string Server::findServerName(HTTPRequest& request, ServerBlock& serverBlock)
{
std::string serverName;

for (size_t j = 0; j < serverBlock.getServerName().size(); j++)
{
serverName = serverBlock.getServerName()[j];
std::cout << RED << "Checking server name: " << serverName << RESET << std::endl;
if (serverName == request.getSingleHeader("host").second)
{
std::cout << GREEN << "Server name found" << RESET << std::endl;
break;
}
}
return serverName;
}
6 changes: 6 additions & 0 deletions src/Server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,16 @@ class Server

/* for handleConnection */
void readFromClient(Connection &conn, size_t &i, Parser &parser, HTTPRequest &request, HTTPResponse &response);
void handlePostRequest(Connection &conn, Parser &parser, HTTPRequest &request, HTTPResponse &response);
void buildResponse(Connection &conn, size_t &i, HTTPRequest &request, HTTPResponse &response);
void writeToClient(Connection &conn, size_t &i, HTTPResponse &response);
void closeClientConnection(Connection &conn, size_t &i);

/* for buildResponse */
void formRequestTarget(HTTPRequest &request);
void findLocationBlock(HTTPRequest &request, ServerBlock& serverBlock, Directives &directive);
void handleServerBlockError(Connection& conn, HTTPResponse &response);
std::string findServerName(HTTPRequest& request, ServerBlock& serverBlock);
/* Not avaiable constructors */
// Copy constructor
Server(const Server &other);
Expand Down
11 changes: 7 additions & 4 deletions src/ServerBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,20 +238,23 @@ void ServerBlock::setIndex(std::vector<std::string> str, bool isLocation)

void ServerBlock::setRoot(std::string &str, bool isLocation)
{
// add a slash at the end if there is none
if (str.size() > 1 && str[str.size() - 1] != '/')
str = str + "/";
// remove slash at the beginning
if (str.size() < 1 && str[0] == '/')
str = str.substr(1);

if (!isLocation)
{
if (_directives._root.size() > 0)
throw("root already set");
if (str[0] == '/')
str = str.substr(1);
_directives._root = str;
}
else
{
if (_locations.back()._root.size() > 0)
throw("root already set");
if (str[0] == '/')
str = str.substr(1);
_locations.back()._root = str;
}
}
Expand Down
Loading

0 comments on commit 3847e1d

Please sign in to comment.