feat: replace URIParser with URI class for improved URI handling

This commit is contained in:
Quinten 2025-10-09 18:02:21 +02:00
parent 0f9fa38d8b
commit 35d17d8fa9
5 changed files with 44 additions and 33 deletions

View File

@ -3,7 +3,7 @@
#include <webserv/handler/ErrorHandler.hpp> // for ErrorHandler #include <webserv/handler/ErrorHandler.hpp> // for ErrorHandler
#include <webserv/handler/FileHandler.hpp> #include <webserv/handler/FileHandler.hpp>
#include <webserv/handler/MIMETypes.hpp> // for MIMETypes #include <webserv/handler/MIMETypes.hpp> // for MIMETypes
#include <webserv/handler/URIParser.hpp> // for URIParser #include <webserv/handler/URI.hpp> // for URI
#include <webserv/http/HttpConstants.hpp> // for NOT_FOUND, FORBIDDEN, OK #include <webserv/http/HttpConstants.hpp> // for NOT_FOUND, FORBIDDEN, OK
#include <webserv/http/HttpResponse.hpp> // for HttpResponse #include <webserv/http/HttpResponse.hpp> // for HttpResponse
#include <webserv/log/Log.hpp> // for Log, LOCATION #include <webserv/log/Log.hpp> // for Log, LOCATION
@ -14,7 +14,7 @@
#include <string> // for basic_string, string, operator+, char_traits #include <string> // for basic_string, string, operator+, char_traits
#include <vector> // for vector #include <vector> // for vector
FileHandler::FileHandler(const AConfig *config, const URIParser &uriParser) : config_(config), uriParser_(uriParser) FileHandler::FileHandler(const AConfig *config, const URI &URI) : config_(config), uri_(URI)
{ {
Log::trace(LOCATION); Log::trace(LOCATION);
} }
@ -67,7 +67,7 @@ std::unique_ptr<HttpResponse> FileHandler::handleDirectory(const std::string &di
std::unique_ptr<HttpResponse> FileHandler::getResponse() const std::unique_ptr<HttpResponse> FileHandler::getResponse() const
{ {
Log::trace(LOCATION); Log::trace(LOCATION);
std::string filepath = uriParser_.getFullPath(); std::string filepath = uri_.getFullPath();
ResourceType resourceType = getResourceType(filepath); ResourceType resourceType = getResourceType(filepath);
switch (resourceType) switch (resourceType)
@ -85,11 +85,11 @@ FileHandler::ResourceType FileHandler::getResourceType(const std::string &path)
static_cast<void>(path); static_cast<void>(path);
Log::trace(LOCATION); Log::trace(LOCATION);
if (uriParser_.isFile()) if (uri_.isFile())
{ {
return FILE; return FILE;
} }
if (uriParser_.isDirectory()) if (uri_.isDirectory())
{ {
if (config_->get<std::vector<std::string>>("index").has_value()) if (config_->get<std::vector<std::string>>("index").has_value())
{ {

View File

@ -3,7 +3,7 @@
#include "webserv/config/AConfig.hpp" #include "webserv/config/AConfig.hpp"
#include <webserv/config/LocationConfig.hpp> #include <webserv/config/LocationConfig.hpp>
#include <webserv/handler/URIParser.hpp> #include <webserv/handler/URI.hpp>
#include <webserv/http/HttpResponse.hpp> // for HttpResponse #include <webserv/http/HttpResponse.hpp> // for HttpResponse
#include <cstdint> // for uint8_t #include <cstdint> // for uint8_t
@ -11,18 +11,18 @@
#include <string> // for string #include <string> // for string
class AConfig; class AConfig;
class URIParser; class URI;
class FileHandler class FileHandler
{ {
public: public:
FileHandler(const AConfig *config, const URIParser &uriParser); FileHandler(const AConfig *config, const URI &uri);
[[nodiscard]] std::unique_ptr<HttpResponse> getResponse() const; [[nodiscard]] std::unique_ptr<HttpResponse> getResponse() const;
private: private:
const AConfig *config_; const AConfig *config_;
const URIParser &uriParser_; const URI &uri_;
enum ResourceType : uint8_t enum ResourceType : uint8_t
{ {

View File

@ -4,21 +4,26 @@
#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
#include <webserv/handler/URIParser.hpp> #include <webserv/handler/URI.hpp>
#include <optional> // for optional #include <optional> // for optional
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
#include <sys/stat.h> // for stat, S_ISDIR, S_ISREG #include <sys/stat.h> // for stat, S_ISDIR, S_ISREG
URIParser::URIParser(const std::string &uri, const ServerConfig &serverConfig) URI::URI(const HttpRequest &request, const ServerConfig &serverConfig)
: uriTrimmed_(utils::trim(uri, "/")), config_(matchConfig(uriTrimmed_, serverConfig)) : uriTrimmed_(utils::trim(request.getTarget(), "/")), config_(matchConfig(uriTrimmed_, serverConfig))
{ {
parseUri(uri); parseUri(request.getTarget());
parseFullpath(); parseFullpath();
authority_ = request.getHeaders().getHost().value();
authority_ += (serverConfig.get<int>("listen") != 80) // NOFORMAT
? ":" + std::to_string(serverConfig.get<int>("listen").value())
: "";
} }
const AConfig *URIParser::matchConfig(const std::string &uri, const ServerConfig &serverConfig) const AConfig *URI::matchConfig(const std::string &uri, const ServerConfig &serverConfig)
{ {
const auto &locations = serverConfig.getLocationPaths(); const auto &locations = serverConfig.getLocationPaths();
const AConfig *bestMatch = &serverConfig; const AConfig *bestMatch = &serverConfig;
@ -42,7 +47,7 @@ const AConfig *URIParser::matchConfig(const std::string &uri, const ServerConfig
return bestMatch; return bestMatch;
} }
void URIParser::parseUri(const std::string &uri) void URI::parseUri(const std::string &uri)
{ {
if (config_->getType() == "server") if (config_->getType() == "server")
{ {
@ -71,7 +76,7 @@ void URIParser::parseUri(const std::string &uri)
} }
} }
void URIParser::parseFullpath() void URI::parseFullpath()
{ {
auto uriSegments = utils::split(fullPath_, '/'); auto uriSegments = utils::split(fullPath_, '/');
@ -99,57 +104,57 @@ void URIParser::parseFullpath()
fullPath_ = FileUtils::joinPath(dir_, baseName_); fullPath_ = FileUtils::joinPath(dir_, baseName_);
} }
const AConfig *URIParser::getConfig() const const AConfig *URI::getConfig() const
{ {
return config_; return config_;
} }
bool URIParser::isFile() const bool URI::isFile() const
{ {
return !baseName_.empty(); return !baseName_.empty();
} }
bool URIParser::isDirectory() const bool URI::isDirectory() const
{ {
return baseName_.empty(); return baseName_.empty();
} }
bool URIParser::isValid() const bool URI::isValid() const
{ {
return FileUtils::isValidPath(fullPath_); return FileUtils::isValidPath(fullPath_);
} }
const std::string &URIParser::getBaseName() const const std::string &URI::getBaseName() const
{ {
return baseName_; return baseName_;
} }
std::string URIParser::getExtension() const std::string URI::getExtension() const
{ {
return FileUtils::getExtension(baseName_); return FileUtils::getExtension(baseName_);
} }
const std::string &URIParser::getFullPath() const const std::string &URI::getFullPath() const
{ {
return fullPath_; return fullPath_;
} }
const std::string &URIParser::getDir() const const std::string &URI::getDir() const
{ {
return dir_; return dir_;
} }
const std::string &URIParser::getPathInfo() const const std::string &URI::getPathInfo() const
{ {
return pathInfo_; return pathInfo_;
} }
const std::string &URIParser::getQuery() const const std::string &URI::getQuery() const
{ {
return query_; return query_;
} }
const std::string &URIParser::getFragment() const const std::string &URI::getFragment() const
{ {
return fragment_; return fragment_;
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "webserv/config/AConfig.hpp" #include "webserv/config/AConfig.hpp"
#include "webserv/http/HttpRequest.hpp"
#include <webserv/config/LocationConfig.hpp> #include <webserv/config/LocationConfig.hpp>
#include <webserv/config/ServerConfig.hpp> #include <webserv/config/ServerConfig.hpp>
@ -11,14 +12,15 @@
class LocationConfig; class LocationConfig;
class ServerConfig; class ServerConfig;
class URIParser class URI
{ {
public: public:
URIParser(const std::string &uri, const ServerConfig &serverConfig); URI(const HttpRequest &request, const ServerConfig &serverConfig);
[[nodiscard]] bool isFile() const; [[nodiscard]] bool isFile() const;
[[nodiscard]] bool isDirectory() const; [[nodiscard]] bool isDirectory() const;
[[nodiscard]] bool isValid() const; [[nodiscard]] bool isValid() const;
[[nodiscard]] bool isCgi() const;
[[nodiscard]] std::string getExtension() const; [[nodiscard]] std::string getExtension() const;
[[nodiscard]] const AConfig *getConfig() const; [[nodiscard]] const AConfig *getConfig() const;
@ -28,6 +30,8 @@ class URIParser
[[nodiscard]] const std::string &getPathInfo() const; [[nodiscard]] const std::string &getPathInfo() const;
[[nodiscard]] const std::string &getQuery() const; [[nodiscard]] const std::string &getQuery() const;
[[nodiscard]] const std::string &getFragment() const; [[nodiscard]] const std::string &getFragment() const;
[[nodiscard]] const std::string &getAuthority() const;
[[nodiscard]] const std::string &getScheme() const;
private: private:
void parseUri(const std::string &uri); void parseUri(const std::string &uri);
@ -41,6 +45,8 @@ class URIParser
std::string pathInfo_; std::string pathInfo_;
std::string query_; std::string query_;
std::string fragment_; std::string fragment_;
std::string authority_;
std::string scheme_;
static const AConfig *matchConfig(const std::string &uri, const ServerConfig &serverConfig); static const AConfig *matchConfig(const std::string &uri, const ServerConfig &serverConfig);
}; };

View File

@ -5,7 +5,7 @@
#include <webserv/config/directive/ADirective.hpp> #include <webserv/config/directive/ADirective.hpp>
#include <webserv/handler/ErrorHandler.hpp> // for ErrorHandler #include <webserv/handler/ErrorHandler.hpp> // for ErrorHandler
#include <webserv/handler/FileHandler.hpp> // for FileHandler #include <webserv/handler/FileHandler.hpp> // for FileHandler
#include <webserv/handler/URIParser.hpp> // for URIParser #include <webserv/handler/URI.hpp> // for URI
#include <webserv/http/HttpHeaders.hpp> // for HttpHeaders #include <webserv/http/HttpHeaders.hpp> // for HttpHeaders
#include <webserv/log/Log.hpp> // for LOCATION, Log #include <webserv/log/Log.hpp> // for LOCATION, Log
#include <webserv/router/Router.hpp> #include <webserv/router/Router.hpp>
@ -40,17 +40,17 @@ std::unique_ptr<HttpResponse> Router::handleRequest(const HttpRequest &request)
{ {
return ErrorHandler::getErrorResponse(400); return ErrorHandler::getErrorResponse(400);
} }
URIParser uriParser{request.getTarget(), *serverConfig}; 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();
const AConfig *config = uriParser.getConfig(); const AConfig *config = uri.getConfig();
if (!isMethodSupported(method, *config)) if (!isMethodSupported(method, *config))
{ {
return ErrorHandler::getErrorResponse(405, config); return ErrorHandler::getErrorResponse(405, config);
} }
FileHandler fileHandler(config, uriParser); FileHandler fileHandler(config, uri);
return fileHandler.getResponse(); return fileHandler.getResponse();
} }