feat(config): add new server configuration for site-3 and implement CGI support
feat(site-3): create index.php for site-3 with a greeting message refactor(client): change setCgiSocket to accept unique_ptr for better memory management fix(AConfig): adjust getCGIPath to correctly prepend dot to extension refactor(CgiProcess): update CGI process handling to use unique_ptr for CgiSocket refactor(URI): enhance logging for CGI checks and improve condition checks refactor(Router): clean up commented code and add debug logging for CGI process fix(Server): improve error logging for epoll_ctl failures
This commit is contained in:
parent
7134e26f6f
commit
0887acd81a
@ -88,3 +88,32 @@ server {
|
|||||||
# cgi_enabled yes;
|
# cgi_enabled yes;
|
||||||
cgi_ext .php /usr/bin/php-cgi;
|
cgi_ext .php /usr/bin/php-cgi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 8082;
|
||||||
|
host 127.0.0.1;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
root ./htdocs/site-3/;
|
||||||
|
index index.html index2.htm;
|
||||||
|
|
||||||
|
error_page 400;
|
||||||
|
error_page 403 /403.html;
|
||||||
|
error_page 404 /404.html;
|
||||||
|
error_page 405 /405.html;
|
||||||
|
error_page 413 /413.html;
|
||||||
|
error_page 500 /500.html;
|
||||||
|
error_page 502 /502.html;
|
||||||
|
error_page 504 /504.html;
|
||||||
|
|
||||||
|
client_max_body_size 1M;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
autoindex off;
|
||||||
|
index index.php;
|
||||||
|
allowed_methods GET POST DELETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
cgi_enabled yes;
|
||||||
|
cgi_ext .php /usr/bin/php-cgi;
|
||||||
|
}
|
||||||
3
htdocs/site-3/index.php
Normal file
3
htdocs/site-3/index.php
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
echo "Hello, World! This is site-3.";
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
#include "webserv/socket/CgiSocket.hpp"
|
||||||
|
|
||||||
#include <webserv/client/Client.hpp>
|
#include <webserv/client/Client.hpp>
|
||||||
#include <webserv/http/HttpHeaders.hpp> // for HttpHeaders
|
#include <webserv/http/HttpHeaders.hpp> // for HttpHeaders
|
||||||
#include <webserv/log/Log.hpp> // for Log, LOCATION
|
#include <webserv/log/Log.hpp> // for Log, LOCATION
|
||||||
@ -9,6 +11,7 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
#include <functional> // for ref, reference_wrapper
|
#include <functional> // for ref, reference_wrapper
|
||||||
#include <map> // for map
|
#include <map> // for map
|
||||||
|
#include <memory>
|
||||||
#include <string> // for basic_string, to_string, operator+, operator<=>
|
#include <string> // for basic_string, to_string, operator+, operator<=>
|
||||||
#include <utility> // for pair, move
|
#include <utility> // for pair, move
|
||||||
|
|
||||||
@ -86,9 +89,10 @@ void Client::request()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::setCgiSocket(CgiSocket &cgiSocket)
|
void Client::setCgiSocket(std::unique_ptr<CgiSocket> cgiSocket)
|
||||||
{
|
{
|
||||||
server_.add(cgiSocket, EPOLLIN | EPOLLOUT);
|
server_.add(*cgiSocket, EPOLLIN, this);
|
||||||
|
cgi_socket_ = std::move(cgiSocket);
|
||||||
// TODO add to handler
|
// TODO add to handler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,7 +43,7 @@ class Client
|
|||||||
[[nodiscard]] ClientSocket &getSocket() const { return *client_socket_; }
|
[[nodiscard]] ClientSocket &getSocket() const { return *client_socket_; }
|
||||||
|
|
||||||
void setStatusCode(int code);
|
void setStatusCode(int code);
|
||||||
void setCgiSocket(CgiSocket &cgiSocket);
|
void setCgiSocket(std::unique_ptr<CgiSocket> cgiSocket);
|
||||||
|
|
||||||
[[nodiscard]] HttpRequest &getHttpRequest() const;
|
[[nodiscard]] HttpRequest &getHttpRequest() const;
|
||||||
[[nodiscard]] HttpResponse &getHttpResponse() const;
|
[[nodiscard]] HttpResponse &getHttpResponse() const;
|
||||||
@ -55,5 +55,6 @@ class Client
|
|||||||
std::unique_ptr<HttpResponse> httpResponse_;
|
std::unique_ptr<HttpResponse> httpResponse_;
|
||||||
std::unique_ptr<Router> router_;
|
std::unique_ptr<Router> router_;
|
||||||
std::unique_ptr<ClientSocket> client_socket_;
|
std::unique_ptr<ClientSocket> client_socket_;
|
||||||
|
std::unique_ptr<CgiSocket> cgi_socket_ = nullptr;
|
||||||
Server &server_;
|
Server &server_;
|
||||||
};
|
};
|
||||||
@ -130,7 +130,7 @@ std::string AConfig::getCGIPath(const std::string &extension) const
|
|||||||
auto exts = directive->getValue().try_get<std::vector<std::string>>().value();
|
auto exts = directive->getValue().try_get<std::vector<std::string>>().value();
|
||||||
auto cgiPath = exts.back();
|
auto cgiPath = exts.back();
|
||||||
exts.pop_back(); // Last element is the CGI path
|
exts.pop_back(); // Last element is the CGI path
|
||||||
auto it = std::ranges::find(exts, extension);
|
auto it = std::ranges::find(exts, "." + extension);
|
||||||
if (it != exts.end())
|
if (it != exts.end())
|
||||||
{
|
{
|
||||||
return cgiPath;
|
return cgiPath;
|
||||||
|
|||||||
@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
#include <webserv/handler/URI.hpp>
|
#include <webserv/handler/URI.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -47,17 +50,18 @@ void CgiProcess::spawn()
|
|||||||
close(sv[1]);
|
close(sv[1]);
|
||||||
|
|
||||||
// Prepare arguments
|
// Prepare arguments
|
||||||
char *args[] = {const_cast<char *>(cgiPath.c_str()), nullptr};
|
std::string fullPath = uri.getFullPath();
|
||||||
|
char *args[] = {const_cast<char *>(cgiPath.c_str()), const_cast<char *>(fullPath.c_str())};
|
||||||
execve(const_cast<char *>(cgiPath.c_str()), args, nullptr);
|
execve(const_cast<char *>(cgiPath.c_str()), args, nullptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Parent process
|
// Parent process
|
||||||
CgiSocket cgiSocket(sv[0]);
|
auto cgiSocket = std::make_unique<CgiSocket>(sv[0]); // CgiSocket wraps sv[0]
|
||||||
close(sv[0]);
|
close(sv[1]);
|
||||||
|
|
||||||
request_.getClient().setCgiSocket(cgiSocket); // move the socket to the client
|
// cgiSocket->write(request_.getBody().data(), request_.getBody().size());
|
||||||
cgiSocket.write(request_.getBody().data(), request_.getBody().size());
|
request_.getClient().setCgiSocket(std::move(cgiSocket)); // move the socket to the client
|
||||||
// _cgiFd can be used to communicate with the CGI process
|
// _cgiFd can be used to communicate with the CGI process
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
#include "webserv/log/Log.hpp"
|
#include "webserv/log/Log.hpp"
|
||||||
|
|
||||||
#include <webserv/config/AConfig.hpp> // for AConfig
|
#include <webserv/config/AConfig.hpp> // for AConfig
|
||||||
#include <webserv/config/LocationConfig.hpp> // for LocationConfig
|
#include <webserv/config/LocationConfig.hpp> // for LocationConfig
|
||||||
#include <webserv/config/ServerConfig.hpp> // for ServerConfig
|
#include <webserv/config/ServerConfig.hpp> // for ServerConfig
|
||||||
@ -155,9 +156,16 @@ bool URI::isCgi() const
|
|||||||
|
|
||||||
std::string URI::getCgiPath() const
|
std::string URI::getCgiPath() const
|
||||||
{
|
{
|
||||||
if (isFile() || getExtension().empty() || !config_->get<std::string>("cgi_enabled").has_value()
|
Log::debug("BaseName: " + baseName_ + ", FullPath: " + fullPath_ + ", Dir: " + dir_ + ", PathInfo: " + pathInfo_ +
|
||||||
|| config_->get<std::string>("cgi_enabled").value() != "on")
|
", Extension: " + getExtension());
|
||||||
|
if (!isFile() || getExtension().empty() || !config_->get<bool>("cgi_enabled").has_value()
|
||||||
|
|| !config_->get<bool>("cgi_enabled").value())
|
||||||
{
|
{
|
||||||
|
Log::debug("CGI not enabled or not a file or no extension",
|
||||||
|
{{"isFile", isFile() ? "true" : "false"},
|
||||||
|
{"extension", getExtension()},
|
||||||
|
{"cgi_enabled", config_->get<bool>("cgi_enabled").has_value() ? "true" : "false"},
|
||||||
|
{"cgi_enabled_value", config_->get<bool>("cgi_enabled").value() ? "true" : "false"}});
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
auto cgiPath = config_->getCGIPath(getExtension());
|
auto cgiPath = config_->getCGIPath(getExtension());
|
||||||
|
|||||||
@ -40,15 +40,6 @@ void Router::handleRequest()
|
|||||||
HttpRequest &request = client_->getHttpRequest();
|
HttpRequest &request = client_->getHttpRequest();
|
||||||
HttpResponse &response = client_->getHttpResponse();
|
HttpResponse &response = client_->getHttpResponse();
|
||||||
|
|
||||||
// ServerConfig *serverConfig
|
|
||||||
// = ConfigManager::getInstance().getMatchingServerConfig(request.getHeaders().getHost().value_or(""));
|
|
||||||
|
|
||||||
// if (serverConfig == nullptr)
|
|
||||||
// {
|
|
||||||
// response = ErrorHandler::getErrorResponse(400);
|
|
||||||
// }
|
|
||||||
// URI uri{request, *serverConfig};
|
|
||||||
|
|
||||||
const std::string &target = request.getTarget();
|
const std::string &target = request.getTarget();
|
||||||
static_cast<void>(target); // Suppress unused variable warning
|
static_cast<void>(target); // Suppress unused variable warning
|
||||||
const std::string &method = request.getMethod();
|
const std::string &method = request.getMethod();
|
||||||
@ -63,6 +54,7 @@ void Router::handleRequest()
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
Log::debug("Starting CGI process");
|
||||||
CgiProcess cgiProcess(request);
|
CgiProcess cgiProcess(request);
|
||||||
// return nullptr; // Response will be handled asynchronously
|
// return nullptr; // Response will be handled asynchronously
|
||||||
}
|
}
|
||||||
@ -72,6 +64,9 @@ void Router::handleRequest()
|
|||||||
// return ErrorHandler::getErrorResponse(500, config);
|
// return ErrorHandler::getErrorResponse(500, config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
FileHandler fileHandler(request, response);
|
FileHandler fileHandler(request, response);
|
||||||
fileHandler.handle();
|
fileHandler.handle();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@ -73,7 +73,7 @@ void Server::add(const ASocket &socket, uint32_t events, Client *client)
|
|||||||
event.data.fd = fd;
|
event.data.fd = fd;
|
||||||
if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &event) == -1)
|
if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &event) == -1)
|
||||||
{
|
{
|
||||||
Log::error("epoll_ctl ADD failed for fd: " + std::to_string(fd));
|
Log::error("epoll_ctl ADD failed for fd: " + std::to_string(fd) + " with error: " + std::strerror(errno));
|
||||||
throw std::runtime_error("epoll_ctl ADD failed");
|
throw std::runtime_error("epoll_ctl ADD failed");
|
||||||
}
|
}
|
||||||
socketToClient_[fd] = client;
|
socketToClient_[fd] = client;
|
||||||
@ -185,8 +185,8 @@ void Server::handleResponse(struct epoll_event *event)
|
|||||||
{
|
{
|
||||||
Log::debug("Attempting to send data to fd: " + std::to_string(event->data.fd));
|
Log::debug("Attempting to send data to fd: " + std::to_string(event->data.fd));
|
||||||
Client &client = getClient(event->data.fd);
|
Client &client = getClient(event->data.fd);
|
||||||
auto httpResponse = client.getResponse();
|
auto payload = client.getResponse();
|
||||||
ssize_t bytesSent = send(event->data.fd, httpResponse.data(), httpResponse.size(), 0);
|
ssize_t bytesSent = send(event->data.fd, payload.data(), payload.size(), 0);
|
||||||
if (bytesSent < 0)
|
if (bytesSent < 0)
|
||||||
{
|
{
|
||||||
Log::error("Send failed for fd: " + std::to_string(event->data.fd) + " with error: " + std::strerror(errno));
|
Log::error("Send failed for fd: " + std::to_string(event->data.fd) + " with error: " + std::strerror(errno));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user