first approximation of the parser
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
/*********************************/
|
||||
/* */
|
||||
/* o.riabenkyi@gmain.com */
|
||||
/* */
|
||||
/*********************************/
|
||||
|
||||
#ifndef CONFIG_HPP
|
||||
#define CONFIG_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "ServerConfig.hpp"
|
||||
|
||||
// Holds every server block parsed from the configuration file and validates
|
||||
// them, both individually and against each other.
|
||||
class Config {
|
||||
public:
|
||||
Config();
|
||||
|
||||
void addServer(const ServerConfig &server);
|
||||
const std::vector<ServerConfig> &getServers() const;
|
||||
|
||||
// Throws std::runtime_error with a descriptive message when invalid.
|
||||
void validate() const;
|
||||
|
||||
private:
|
||||
std::vector<ServerConfig> _servers;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
/*********************************/
|
||||
/* */
|
||||
/* o.riabenkyi@gmain.com */
|
||||
/* */
|
||||
/*********************************/
|
||||
|
||||
#ifndef CONFIGURATIONPARSER_HPP
|
||||
#define CONFIGURATIONPARSER_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Config.hpp"
|
||||
#include "LocationConfig.hpp"
|
||||
#include "ServerConfig.hpp"
|
||||
|
||||
// Reads a webserv configuration file and turns it into a validated Config.
|
||||
//
|
||||
// Syntax (see webserv_design_notes.md):
|
||||
// - one logical line is exactly one syntactic unit: a block opener
|
||||
// ("server {" / "location /path {"), a lone closing "}", or a single
|
||||
// directive followed by its values
|
||||
// - '#' starts a comment that runs to the end of the line, stripped
|
||||
// before tokenizing
|
||||
// - there is no ';' terminator - a directive's values are simply the
|
||||
// remaining tokens on its line
|
||||
// - a closing "}" must appear alone on its own line
|
||||
class ConfigurationParser {
|
||||
public:
|
||||
ConfigurationParser();
|
||||
~ConfigurationParser();
|
||||
|
||||
// Reads the file at `path`, parses it and returns a validated Config.
|
||||
// Throws std::runtime_error on any syntax or validation error.
|
||||
Config parse(const std::string &path);
|
||||
|
||||
private:
|
||||
std::vector<std::vector<std::string> > _lines;
|
||||
size_t _pos;
|
||||
|
||||
std::string readFile(const std::string &path) const;
|
||||
void tokenizeLines(const std::string &content);
|
||||
static std::string stripComment(const std::string &line);
|
||||
static std::vector<std::string> splitTokens(const std::string &line);
|
||||
static std::string joinTokens(const std::vector<std::string> &tokens);
|
||||
|
||||
bool hasNext() const;
|
||||
const std::vector<std::string> &peek() const;
|
||||
std::vector<std::string> next();
|
||||
|
||||
ServerConfig parseServerBlock();
|
||||
LocationConfig parseLocationBlock(const std::string &path);
|
||||
void applyServerDirective(ServerConfig &server, const std::string &name,
|
||||
const std::vector<std::string> &values);
|
||||
void applyLocationDirective(LocationConfig &location, const std::string &name,
|
||||
const std::vector<std::string> &values);
|
||||
|
||||
static int toInt(const std::string &s);
|
||||
static size_t parseSize(const std::string &s);
|
||||
|
||||
ConfigurationParser(const ConfigurationParser &other);
|
||||
ConfigurationParser &operator=(const ConfigurationParser &other);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,73 @@
|
||||
/*********************************/
|
||||
/* */
|
||||
/* o.riabenkyi@gmain.com */
|
||||
/* */
|
||||
/*********************************/
|
||||
|
||||
#ifndef LOCATIONCONFIG_HPP
|
||||
#define LOCATIONCONFIG_HPP
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// One "location { ... }" block: routing rules for one path prefix.
|
||||
//
|
||||
// | Directive | Purpose |
|
||||
// | `methods` | permitted HTTP methods |
|
||||
// | `root` | root directory on the disk |
|
||||
// | `autoindex` | directory listing on/off |
|
||||
// | `index` | default file for the directory |
|
||||
// | `return` | HTTP redirect (status code + URL) |
|
||||
// | `upload_store` | path for storing uploaded files |
|
||||
// | `cgi_extension`| file extension → CGI |
|
||||
// | `cgi_pass` | path to the CGI executable file |
|
||||
|
||||
|
||||
class LocationConfig {
|
||||
public:
|
||||
struct Redirect {
|
||||
int code;
|
||||
std::string url;
|
||||
};
|
||||
|
||||
LocationConfig();
|
||||
|
||||
void setPath(const std::string &path);
|
||||
void setRoot(const std::string &root);
|
||||
void setMethods(const std::vector<std::string> &methods);
|
||||
void setAutoindex(bool autoindex);
|
||||
void setIndex(const std::string &index);
|
||||
void setReturn(int code, const std::string &url);
|
||||
void setUploadStore(const std::string &uploadStore);
|
||||
void setCgiExtension(const std::string &extension);
|
||||
void setCgiPass(const std::string &pass);
|
||||
|
||||
const std::string &getPath() const;
|
||||
const std::optional<std::string> &getRoot() const;
|
||||
const std::vector<std::string> &getMethods() const;
|
||||
bool getAutoindex() const;
|
||||
const std::optional<std::string> &getIndex() const;
|
||||
const std::optional<Redirect> &getReturn() const;
|
||||
const std::optional<std::string> &getUploadStore() const;
|
||||
const std::optional<std::string> &getCgiExtension() const;
|
||||
const std::optional<std::string> &getCgiPass() const;
|
||||
|
||||
// Throws std::runtime_error with a descriptive message when invalid.
|
||||
// Does not check root inheritance - the owning ServerConfig does that,
|
||||
// since it alone knows whether a server-level root is available.
|
||||
void validate() const;
|
||||
|
||||
private:
|
||||
std::string _path;
|
||||
std::optional<std::string> _root;
|
||||
std::vector<std::string> _methods;
|
||||
bool _autoindex;
|
||||
std::optional<std::string> _index;
|
||||
std::optional<Redirect> _return;
|
||||
std::optional<std::string> _uploadStore;
|
||||
std::optional<std::string> _cgiExtension;
|
||||
std::optional<std::string> _cgiPass;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,58 @@
|
||||
/*********************************/
|
||||
/* */
|
||||
/* o.riabenkyi@gmain.com */
|
||||
/* */
|
||||
/*********************************/
|
||||
|
||||
#ifndef SERVERCONFIG_HPP
|
||||
#define SERVERCONFIG_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "LocationConfig.hpp"
|
||||
|
||||
// One "server { ... }" block: everything needed to run a single virtual server.
|
||||
class ServerConfig {
|
||||
public:
|
||||
struct Listen {
|
||||
std::string host;
|
||||
int port;
|
||||
};
|
||||
|
||||
ServerConfig();
|
||||
|
||||
void addListen(const std::string &host, int port);
|
||||
void addServerName(const std::string &name);
|
||||
void setRoot(const std::string &root);
|
||||
void setClientMaxBodySize(size_t size);
|
||||
void addErrorPage(int code, const std::string &path);
|
||||
void addLocation(const LocationConfig &location);
|
||||
|
||||
const std::vector<Listen> &getListens() const;
|
||||
const std::vector<std::string> &getServerNames() const;
|
||||
const std::optional<std::string> &getRoot() const;
|
||||
size_t getClientMaxBodySize() const;
|
||||
const std::map<int, std::string> &getErrorPages() const;
|
||||
const std::vector<LocationConfig> &getLocations() const;
|
||||
|
||||
// Returns the location's own root if set, otherwise this server's root.
|
||||
// Only meaningful once validate() has confirmed one of the two exists.
|
||||
const std::string &resolveRoot(const LocationConfig &location) const;
|
||||
|
||||
// Throws std::runtime_error with a descriptive message when invalid.
|
||||
void validate() const;
|
||||
|
||||
private:
|
||||
std::vector<Listen> _listens;
|
||||
std::vector<std::string> _serverNames;
|
||||
std::optional<std::string> _root;
|
||||
size_t _clientMaxBodySize;
|
||||
std::map<int, std::string> _errorPages;
|
||||
std::vector<LocationConfig> _locations;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user