8#include "../includes/ConfigParser.hpp"
32 std::ostringstream ss;
39 std::vector<ServerConf> servers;
42 if (
_peek() !=
"server")
60 while (i < content.size())
62 const char c = content[i];
71 while (i < content.size() && content[i] !=
'\n')
76 if (c ==
'{' || c ==
'}' || c ==
';')
78 _tokens.push_back(std::string(1, c));
84 while (i < content.size()
85 && !std::isspace(content[i])
93 _tokens.push_back(content.substr(start, i - start));
111 const std::string& t =
_peek();
130 const std::string directive =
_consume();
132 if (directive ==
"listen")
134 else if (directive ==
"server_name")
136 else if (directive ==
"client_max_body_size")
138 else if (directive ==
"error_page")
140 else if (directive ==
"location")
142 const std::string path =
_consume();
147 throw ConfigException(
"unknown server directive: '" + directive +
"'");
160 const std::string directive =
_consume();
162 if (directive ==
"root")
164 else if (directive ==
"methods")
166 else if (directive ==
"autoindex")
168 else if (directive ==
"index")
170 else if (directive ==
"upload_store")
172 else if (directive ==
"return")
174 else if (directive ==
"cgi_interpreter")
177 throw ConfigException(
"unknown location directive: '" + directive +
"'");
186 const std::string value =
_consume();
193 const std::string name =
_consume();
200 const std::string value =
_consume();
207 const std::string code =
_consume();
208 const std::string path =
_consume();
211 if (code.size() != 3 || code.find_first_not_of(
"0123456789") != std::string::npos)
219 const std::string root =
_consume();
227 throw ConfigException(
"'methods' directive requires at least one method");
237 const std::string value =
_consume();
242 else if (value ==
"off")
245 throw ConfigException(
"autoindex must be 'on' or 'off', got: '" + value +
"'");
250 const std::string page =
_consume();
264 const std::string code =
_consume();
268 if (code.find_first_not_of(
"0123456789") != std::string::npos)
277 const std::string path =
_consume();
283struct sockaddr_in
ConfigParser::_parseSockAddr(const std::string& listenValue)
285 struct sockaddr_in addr;
286 std::memset(&addr, 0,
sizeof(addr));
287 addr.sin_family = AF_INET;
289 size_t colon = listenValue.find(
':');
290 if (colon != std::string::npos)
292 const std::string ipStr = listenValue.substr(0, colon);
293 const std::string portStr = listenValue.substr(colon + 1);
295 if (portStr.empty() || portStr.find_first_not_of(
"0123456789") != std::string::npos)
298 const int port = std::atoi(portStr.c_str());
299 if (port <= 0 || port > 65535)
300 throw ConfigException(
"port out of range in listen: '" + portStr +
"'");
303 throw ConfigException(
"invalid IP address in listen: '" + ipStr +
"'");
305 struct addrinfo hints;
306 std::memset(&hints, 0,
sizeof(hints));
307 hints.ai_family = AF_INET;
308 hints.ai_socktype = SOCK_STREAM;
310 struct addrinfo* result = NULL;
311 int rc = getaddrinfo(ipStr.c_str(), NULL, &hints, &result);
312 if (rc != 0 || result == NULL)
315 const struct sockaddr_in* resolved =
316 reinterpret_cast<const struct sockaddr_in*
>(result->ai_addr);
317 addr.sin_addr = resolved->sin_addr;
318 freeaddrinfo(result);
320 addr.sin_port = htons(
static_cast<uint16_t
>(port));
324 if (listenValue.empty() || listenValue.find_first_not_of(
"0123456789") != std::string::npos)
327 const int port = std::atoi(listenValue.c_str());
328 if (port <= 0 || port > 65535)
329 throw ConfigException(
"port out of range in listen: '" + listenValue +
"'");
331 addr.sin_addr.s_addr = htonl(INADDR_ANY);
332 addr.sin_port = htons(
static_cast<uint16_t
>(port));
341 const char suffix = value[value.size() - 1];
342 size_t multiplier = 1;
343 std::string numStr = value;
345 if (suffix ==
'k' || suffix ==
'K')
348 numStr = value.substr(0, value.size() - 1);
350 else if (suffix ==
'm' || suffix ==
'M')
352 multiplier = 1024 * 1024;
353 numStr = value.substr(0, value.size() - 1);
355 else if (suffix ==
'g' || suffix ==
'G')
357 multiplier = 1024UL * 1024 * 1024;
358 numStr = value.substr(0, value.size() - 1);
361 if (numStr.empty() || numStr.find_first_not_of(
"0123456789") != std::string::npos)
362 throw ConfigException(
"invalid client_max_body_size value: '" + value +
"'");
364 return static_cast<size_t>(std::atol(numStr.c_str())) * multiplier;
373 if (token ==
"DELETE")
HTTPMethod
Represents the HTTP methods supported by the server as a bitmask.
virtual ~ConfigException()
ConfigException(const std::string &msg)
const std::string & _consume()
struct sockaddr_in _parseSockAddr(const std::string &listenValue)
std::vector< ServerConf > parse()
Parses the config file and returns one ServerConf per server block.
void _parseUploadStore(LocationConf &loc)
void _parseRoot(LocationConf &loc)
ServerConf _parseServerBlock()
LocationConf _parseLocationBlock(const std::string &path)
void _parseMethods(LocationConf &loc)
void _parseMaxBodySize(ServerConf &conf)
void _parseServerName(ServerConf &conf)
ConfigParser(const std::string &filePath)
void _parseIndex(LocationConf &loc)
const std::string & _peek() const
void _tokenize(const std::string &content)
void _expect(const std::string &token)
void _parseErrorPage(ServerConf &conf)
void _parseCgiInterpreter(LocationConf &loc)
void _parseListen(ServerConf &conf)
std::vector< std::string > _tokens
HTTPMethod _parseMethodToken(const std::string &token)
void _parseAutoIndex(LocationConf &loc)
size_t _parseBodySize(const std::string &value)
void _parseReturn(LocationConf &loc)
void setDefaultPage(const std::string &defaultPage)
void addAllowedMethod(HTTPMethod method)
void setAutoIndex(bool autoIndex)
void addCgiInterpreter(const std::string &ext, const std::string &interpreterPath)
void setReturnURL(const std::string &url)
void setReturnCode(const std::string &code)
void setRoot(const std::string &root)
void setPath(const std::string &path)
void setStorageLocation(const std::string &storageLocation)
void setInterfacePortPair(const struct sockaddr_in &address)
void addErrorPage(const std::string &errorCode, const std::string &errorPagePath)
Adds a custom error page mapping (e.g., "404" -> "/errors/404.html").
void addLocation(const LocationConf &location)
Adds a parsed LocationConf block to this server.
void setServerName(const std::string &name)
void setMaxBodySize(size_t size)