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
@ -87,4 +87,33 @@ server {
|
||||
|
||||
# cgi_enabled yes;
|
||||
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/http/HttpHeaders.hpp> // for HttpHeaders
|
||||
#include <webserv/log/Log.hpp> // for Log, LOCATION
|
||||
@ -9,8 +11,9 @@
|
||||
#include <exception>
|
||||
#include <functional> // for ref, reference_wrapper
|
||||
#include <map> // for map
|
||||
#include <string> // for basic_string, to_string, operator+, operator<=>
|
||||
#include <utility> // for pair, move
|
||||
#include <memory>
|
||||
#include <string> // for basic_string, to_string, operator+, operator<=>
|
||||
#include <utility> // for pair, move
|
||||
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/types.h> // for ssize_t
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ class Client
|
||||
[[nodiscard]] ClientSocket &getSocket() const { return *client_socket_; }
|
||||
|
||||
void setStatusCode(int code);
|
||||
void setCgiSocket(CgiSocket &cgiSocket);
|
||||
void setCgiSocket(std::unique_ptr<CgiSocket> cgiSocket);
|
||||
|
||||
[[nodiscard]] HttpRequest &getHttpRequest() const;
|
||||
[[nodiscard]] HttpResponse &getHttpResponse() const;
|
||||
@ -55,5 +55,6 @@ class Client
|
||||
std::unique_ptr<HttpResponse> httpResponse_;
|
||||
std::unique_ptr<Router> router_;
|
||||
std::unique_ptr<ClientSocket> client_socket_;
|
||||
std::unique_ptr<CgiSocket> cgi_socket_ = nullptr;
|
||||
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 cgiPath = exts.back();
|
||||
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())
|
||||
{
|
||||
return cgiPath;
|
||||
|
||||
@ -5,6 +5,9 @@
|
||||
|
||||
#include <webserv/handler/URI.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@ -47,17 +50,18 @@ void CgiProcess::spawn()
|
||||
close(sv[1]);
|
||||
|
||||
// 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parent process
|
||||
CgiSocket cgiSocket(sv[0]);
|
||||
close(sv[0]);
|
||||
auto cgiSocket = std::make_unique<CgiSocket>(sv[0]); // CgiSocket wraps 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
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
#include "webserv/log/Log.hpp"
|
||||
|
||||
#include <webserv/config/AConfig.hpp> // for AConfig
|
||||
#include <webserv/config/LocationConfig.hpp> // for LocationConfig
|
||||
#include <webserv/config/ServerConfig.hpp> // for ServerConfig
|
||||
@ -155,9 +156,16 @@ bool URI::isCgi() const
|
||||
|
||||
std::string URI::getCgiPath() const
|
||||
{
|
||||
if (isFile() || getExtension().empty() || !config_->get<std::string>("cgi_enabled").has_value()
|
||||
|| config_->get<std::string>("cgi_enabled").value() != "on")
|
||||
Log::debug("BaseName: " + baseName_ + ", FullPath: " + fullPath_ + ", Dir: " + dir_ + ", PathInfo: " + pathInfo_ +
|
||||
", 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 "";
|
||||
}
|
||||
auto cgiPath = config_->getCGIPath(getExtension());
|
||||
|
||||
@ -40,21 +40,12 @@ void Router::handleRequest()
|
||||
HttpRequest &request = client_->getHttpRequest();
|
||||
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();
|
||||
static_cast<void>(target); // Suppress unused variable warning
|
||||
const std::string &method = request.getMethod();
|
||||
|
||||
const AConfig *config = request.getUri().getConfig();
|
||||
|
||||
|
||||
if (!isMethodSupported(method, *config))
|
||||
{
|
||||
// return ErrorHandler::getErrorResponse(405, config);
|
||||
@ -63,6 +54,7 @@ void Router::handleRequest()
|
||||
{
|
||||
try
|
||||
{
|
||||
Log::debug("Starting CGI process");
|
||||
CgiProcess cgiProcess(request);
|
||||
// return nullptr; // Response will be handled asynchronously
|
||||
}
|
||||
@ -72,6 +64,9 @@ void Router::handleRequest()
|
||||
// return ErrorHandler::getErrorResponse(500, config);
|
||||
}
|
||||
}
|
||||
FileHandler fileHandler(request, response);
|
||||
fileHandler.handle();
|
||||
else
|
||||
{
|
||||
FileHandler fileHandler(request, response);
|
||||
fileHandler.handle();
|
||||
}
|
||||
}
|
||||
@ -73,7 +73,7 @@ void Server::add(const ASocket &socket, uint32_t events, Client *client)
|
||||
event.data.fd = fd;
|
||||
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");
|
||||
}
|
||||
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));
|
||||
Client &client = getClient(event->data.fd);
|
||||
auto httpResponse = client.getResponse();
|
||||
ssize_t bytesSent = send(event->data.fd, httpResponse.data(), httpResponse.size(), 0);
|
||||
auto payload = client.getResponse();
|
||||
ssize_t bytesSent = send(event->data.fd, payload.data(), payload.size(), 0);
|
||||
if (bytesSent < 0)
|
||||
{
|
||||
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