well, restructured things a bit, but mostly started trying to sort LocationConfigs, it is sort of going well, good ideas, implementations is still a bit lacking...
This commit is contained in:
6
Makefile
6
Makefile
@@ -23,9 +23,9 @@ SRCS = main.cpp \
|
|||||||
base.cpp init.cpp close.cpp epoll_update.cpp signal.cpp \
|
base.cpp init.cpp close.cpp epoll_update.cpp signal.cpp \
|
||||||
accept.cpp request.cpp response.cpp \
|
accept.cpp request.cpp response.cpp \
|
||||||
run_loop.cpp \
|
run_loop.cpp \
|
||||||
ConfigParser.cpp \
|
parser.cpp \
|
||||||
ConfigParserUtils.cpp \
|
extraConfig.cpp \
|
||||||
ConfigParserPost.cpp \
|
postProcessing.cpp \
|
||||||
utils.cpp \
|
utils.cpp \
|
||||||
cgi_script.cpp \
|
cgi_script.cpp \
|
||||||
Client.cpp \
|
Client.cpp \
|
||||||
|
|||||||
@@ -10,22 +10,42 @@ server {
|
|||||||
# client_body_limit 400;
|
# client_body_limit 400;
|
||||||
|
|
||||||
index index.html; # this is another comment
|
index index.html; # this is another comment
|
||||||
root /website;
|
# root goop;
|
||||||
|
root www;
|
||||||
|
# root www/test; # also works
|
||||||
|
# root /www; # stat does not like this kind of definition
|
||||||
|
# root /usr; # because it's looking at / aka absolute path
|
||||||
|
# root ~/Programming/42/group_webserv/www; # didn't like thise either
|
||||||
|
# root /home/me/Programming/42/group_webserv; # but this is fine
|
||||||
|
|
||||||
|
location /test {
|
||||||
|
root www/test;
|
||||||
|
index index.html;
|
||||||
|
}
|
||||||
# If not explicitly set, ConfigParser need to genererate a location block
|
# If not explicitly set, ConfigParser need to genererate a location block
|
||||||
# like this for path "/" (based on field "root" and "index" of the server)
|
# like this for path "/" (based on field "root" and "index" of the server)
|
||||||
location / {
|
location / {
|
||||||
root ./www/;
|
root www;
|
||||||
index index.html;
|
index index.html;
|
||||||
|
allow_methods DELETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
allow_methods GET;
|
allow_methods GET POST;
|
||||||
|
|
||||||
|
|
||||||
|
location /something/long/here {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
location /something/long/here/but/more {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# ok in theory if one were to go to /test they would get the index in www
|
# ok in theory if one were to go to /test they would get the index in www
|
||||||
# as opposed to the one in /website...
|
# as opposed to the one in /website...
|
||||||
location /test {
|
# location /test {
|
||||||
root /www;
|
# root /www;
|
||||||
}
|
# }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,9 @@
|
|||||||
# include <iostream> // cout, cin
|
# include <iostream> // cout, cin
|
||||||
# include <fstream> // ifstream
|
# include <fstream> // ifstream
|
||||||
//# include <unistd.h> // access()
|
//# include <unistd.h> // access()
|
||||||
# include <dirent.h> // opendir()
|
# include <dirent.h> // opendir(), doesn't work...
|
||||||
|
# include <sys/stat.h> // stat(), replaces opendir() don't bother with ERRNO ?
|
||||||
|
# include <algorithm> // sort() in Post
|
||||||
|
|
||||||
class ConfigParser {
|
class ConfigParser {
|
||||||
|
|
||||||
@@ -51,6 +52,13 @@ public:
|
|||||||
// private member functions from anywhere...
|
// private member functions from anywhere...
|
||||||
void _print_content() const;
|
void _print_content() const;
|
||||||
|
|
||||||
|
|
||||||
|
// I don't love that this is here but...
|
||||||
|
// doesn't work use the operator overload
|
||||||
|
// bool compareLocationConfigs(const LocationConfig &a, const LocationConfig &b);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _content;
|
std::string _content;
|
||||||
|
|
||||||
@@ -82,11 +90,20 @@ private:
|
|||||||
|
|
||||||
void _post_processing(std::vector<ServerConfig> *servers);
|
void _post_processing(std::vector<ServerConfig> *servers);
|
||||||
|
|
||||||
|
bool _find_root_path_location(std::vector<LocationConfig> locations); // const?
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// no idea if it should go here...
|
||||||
|
//bool compareLocationConfigs(const LocationConfig &a,
|
||||||
|
// const LocationConfig &b);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// def needs work line a better name an do i even need this?
|
// def needs work line a better name an do i even need this?
|
||||||
// should it be in Utils instead?
|
// should it be in Utils instead?
|
||||||
class MyException : public std::invalid_argument
|
class MyException : public std::invalid_argument
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "ConfigParser.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ConfigParser::_post_processing(std::vector<ServerConfig> *servers)
|
|
||||||
{
|
|
||||||
|
|
||||||
// make certain servers default
|
|
||||||
// fill out empty settings
|
|
||||||
// if special settings are empty throw
|
|
||||||
|
|
||||||
std::vector<ServerConfig>::iterator it = servers->begin();
|
|
||||||
|
|
||||||
while (it != servers->end())
|
|
||||||
{
|
|
||||||
// host and port should already be set
|
|
||||||
if (it->host == "")
|
|
||||||
throw std::invalid_argument("Config file needs a host and port");
|
|
||||||
|
|
||||||
// is that a good default?
|
|
||||||
if (it->root == "")
|
|
||||||
it->root = "/";
|
|
||||||
if (it->client_body_limit == 0)
|
|
||||||
it->client_body_limit = 5000; // what is the recomended size?
|
|
||||||
|
|
||||||
// autoindex should already be false by default right?
|
|
||||||
|
|
||||||
// what do we do if Allow methods is left empty?
|
|
||||||
// all ?
|
|
||||||
if (it->allow_methods.empty())
|
|
||||||
throw std::invalid_argument("No methods specified");
|
|
||||||
|
|
||||||
|
|
||||||
// what to do if index is left empty? index.html?
|
|
||||||
// ok but i still need to check index, no idea how...
|
|
||||||
|
|
||||||
// if error_pages is left empty, we'll use the defaults which
|
|
||||||
// i believe are set elsewhere...
|
|
||||||
|
|
||||||
std::vector<LocationConfig>::iterator it_l = it->locations.begin();
|
|
||||||
while (it_l != it->locations.end())
|
|
||||||
{
|
|
||||||
// check that path is feasible...
|
|
||||||
// opendir?
|
|
||||||
DIR* dir = opendir(it_l->path.c_str());
|
|
||||||
if (dir)
|
|
||||||
closedir(dir);
|
|
||||||
else
|
|
||||||
throw std::invalid_argument("location dir could not be opened");
|
|
||||||
|
|
||||||
if (it_l->client_body_limit == 0)
|
|
||||||
it_l->client_body_limit = 5000; // what is the recomended size?
|
|
||||||
if (it_l->root == "")
|
|
||||||
it_l->root = it->root;
|
|
||||||
|
|
||||||
// fill out allow methods from server?
|
|
||||||
if (it_l->allow_methods.empty())
|
|
||||||
it_l->allow_methods = it->allow_methods;
|
|
||||||
|
|
||||||
// fill out index from Server?
|
|
||||||
// or do a bunch of checks on what is in there...
|
|
||||||
|
|
||||||
// same for redirect status i think
|
|
||||||
|
|
||||||
// maybe do something for Cgi_info?
|
|
||||||
|
|
||||||
++it_l;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
|
|
||||||
// do the defaults at the end?
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -16,7 +16,9 @@
|
|||||||
# include <map>
|
# include <map>
|
||||||
# include <vector>
|
# include <vector>
|
||||||
# include <string>
|
# include <string>
|
||||||
|
# include <iostream>
|
||||||
|
|
||||||
|
# include "utils.hpp"
|
||||||
|
|
||||||
// again, struct instead?
|
// again, struct instead?
|
||||||
class LocationConfig
|
class LocationConfig
|
||||||
@@ -24,12 +26,18 @@ class LocationConfig
|
|||||||
public:
|
public:
|
||||||
// canonic stuff?
|
// canonic stuff?
|
||||||
|
|
||||||
|
// i thought this might fix the "non static member function"
|
||||||
|
// shit i'm getting with the comparator...
|
||||||
|
LocationConfig() {}
|
||||||
|
~LocationConfig() {}
|
||||||
|
|
||||||
|
|
||||||
std::string path;
|
std::string path;
|
||||||
|
|
||||||
int client_body_limit;
|
int client_body_limit;
|
||||||
std::string root;
|
std::string root;
|
||||||
std::vector<std::string> index;
|
std::vector<std::string> index;
|
||||||
std::vector<http_method> allow_methods;
|
unsigned int allow_methods;
|
||||||
std::map<std::string, std::string> cgi_info;
|
std::map<std::string, std::string> cgi_info;
|
||||||
|
|
||||||
// wait if i can call several times, shouldn't it be a map?
|
// wait if i can call several times, shouldn't it be a map?
|
||||||
@@ -40,10 +48,57 @@ public:
|
|||||||
// au pire you do location / { return 301 http://location; }
|
// au pire you do location / { return 301 http://location; }
|
||||||
// and that's how you get the redirect from the root.
|
// and that's how you get the redirect from the root.
|
||||||
|
|
||||||
|
void print_all()
|
||||||
|
{
|
||||||
|
std::cout << "\nPRINTING A LOCATION\n";
|
||||||
|
|
||||||
|
std::cout << "Path: " << path << '\n';
|
||||||
|
std::cout << "client_body_limit: " << client_body_limit << '\n';
|
||||||
|
std::cout << "root: " << root << '\n';
|
||||||
|
|
||||||
|
std::cout << "Skipping index...\n";
|
||||||
|
|
||||||
|
std::cout << "Location allow_methods: ";
|
||||||
|
std::cout << ::http_methods_to_str(allow_methods) << "\n";
|
||||||
|
|
||||||
|
std::cout << "Skipping redirect status etc...\n";
|
||||||
|
|
||||||
|
std::cout << "------\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// works a lot better than using a compare function...
|
||||||
|
bool operator<(const LocationConfig& rhs) const
|
||||||
|
{
|
||||||
|
size_t len_lhs = 0;
|
||||||
|
size_t len_rhs = 0;
|
||||||
|
size_t tmp = 0;
|
||||||
|
|
||||||
|
// consider adding 1 to path that ends in a file not folder.
|
||||||
|
|
||||||
|
while ((tmp = this->path.find_first_of("/", tmp)) != std::string::npos)
|
||||||
|
{
|
||||||
|
std::cout << "tmp_lhs: " << tmp << "\n";
|
||||||
|
++tmp;
|
||||||
|
++len_lhs;
|
||||||
|
}
|
||||||
|
tmp = 0;
|
||||||
|
while ((tmp = rhs.path.find_first_of("/", tmp)) != std::string::npos)
|
||||||
|
{
|
||||||
|
std::cout << "tmp_rhs: " << tmp << "\n";
|
||||||
|
++tmp;
|
||||||
|
++len_rhs;
|
||||||
|
}
|
||||||
|
std::cout << "len_lhs: " << len_lhs << " len_rhs: " << len_rhs << (len_lhs < len_rhs) << "\n";
|
||||||
|
return (len_lhs < len_rhs); // right comparison ? not <= ?
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ok it needs to go somewhere else
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -32,17 +32,15 @@ public:
|
|||||||
|
|
||||||
int client_body_limit; // set to default max if none set
|
int client_body_limit; // set to default max if none set
|
||||||
|
|
||||||
// might be the only one we let slide if bad input...
|
// might be the only one we let slide if bad input... It remains false...
|
||||||
bool autoindex;
|
bool autoindex;
|
||||||
|
|
||||||
// we will check the index in the post processing with access() ?
|
// we will check the index in the post processing with access() ?
|
||||||
std::vector<std::string> index;
|
std::vector<std::string> index;
|
||||||
std::map<int, std::string> error_pages;
|
std::map<int, std::string> error_pages;
|
||||||
|
|
||||||
// i'm tempted to do something diff for storing method types...
|
|
||||||
// fuck it, you can only call allow_methods once in Server
|
// fuck it, you can only call allow_methods once in Server
|
||||||
// once more in each location.
|
unsigned int allow_methods;
|
||||||
std::vector<http_method> allow_methods;
|
|
||||||
|
|
||||||
std::vector<LocationConfig> locations;
|
std::vector<LocationConfig> locations;
|
||||||
|
|
||||||
@@ -74,10 +72,12 @@ public:
|
|||||||
// for (size_t i = 0; i < error_pages.size(); i++)
|
// for (size_t i = 0; i < error_pages.size(); i++)
|
||||||
// std::cout << error_pages->first << "--" << error_pages->second << " ";
|
// std::cout << error_pages->first << "--" << error_pages->second << " ";
|
||||||
std::cout << "\nallow_methods: ";
|
std::cout << "\nallow_methods: ";
|
||||||
for (size_t i = 0; i < allow_methods.size(); i++)
|
std::cout << ::http_methods_to_str(allow_methods) << "\n";
|
||||||
std::cout << allow_methods[i] << " ";
|
|
||||||
std::cout << "\nskiping Locations for now...\n";
|
// std::cout << "skiping Locations for now...\n";
|
||||||
std::cout << "also skiping send_timeout and recv\n";
|
for (std::vector<LocationConfig>::iterator it = locations.begin(); it < locations.end(); it++)
|
||||||
|
it->print_all();
|
||||||
|
|
||||||
std::cout << "autoindex: " << autoindex << '\n';
|
std::cout << "autoindex: " << autoindex << '\n';
|
||||||
std::cout << "client_body_limit: " << client_body_limit << '\n';
|
std::cout << "client_body_limit: " << client_body_limit << '\n';
|
||||||
// std::cout << "redirect_status: " << redirect_status << '\n';
|
// std::cout << "redirect_status: " << redirect_status << '\n';
|
||||||
|
|||||||
27
srcs/config/compareLocationConfigs.cpp
Normal file
27
srcs/config/compareLocationConfigs.cpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
|
||||||
|
// prolly get rid of this file...
|
||||||
|
|
||||||
|
|
||||||
|
#include "LocationConfig.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
// Ok so maybe it can't be a member functions?
|
||||||
|
bool compareLocationConfigs(const LocationConfig &a, const LocationConfig &b)
|
||||||
|
{
|
||||||
|
int len_a;
|
||||||
|
int len_b;
|
||||||
|
size_t tmp = 0;
|
||||||
|
|
||||||
|
// consider adding 1 to path that ends in a file not folder.
|
||||||
|
|
||||||
|
|
||||||
|
while ((tmp = a.path.find_first_of("/", tmp)) != std::string::npos)
|
||||||
|
++len_a;
|
||||||
|
tmp = 0;
|
||||||
|
while ((tmp = b.path.find_first_of("/", tmp)) != std::string::npos)
|
||||||
|
++len_b;
|
||||||
|
return (len_a < len_b); // right comparison ? not <= ?
|
||||||
|
}
|
||||||
@@ -105,6 +105,7 @@ ServerConfig ConfigParser::_parse_server(size_t *start)
|
|||||||
|
|
||||||
ret.client_body_limit = 0;
|
ret.client_body_limit = 0;
|
||||||
ret.autoindex = false;
|
ret.autoindex = false;
|
||||||
|
ret.allow_methods = 0;
|
||||||
if (curr == std::string::npos || _content[curr] != '{')
|
if (curr == std::string::npos || _content[curr] != '{')
|
||||||
throw std::invalid_argument("bad config file syntax 1");
|
throw std::invalid_argument("bad config file syntax 1");
|
||||||
|
|
||||||
@@ -144,6 +145,7 @@ LocationConfig ConfigParser::_parse_location(size_t *start)
|
|||||||
|
|
||||||
ret.client_body_limit = 0;
|
ret.client_body_limit = 0;
|
||||||
ret.redirect_status = 0;
|
ret.redirect_status = 0;
|
||||||
|
ret.allow_methods = 0;
|
||||||
ret.path = _get_first_word(&curr);
|
ret.path = _get_first_word(&curr);
|
||||||
// in theory now curr should be right after the "path"
|
// in theory now curr should be right after the "path"
|
||||||
|
|
||||||
@@ -176,9 +178,6 @@ LocationConfig ConfigParser::_parse_location(size_t *start)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ConfigParser::_set_server_values(ServerConfig *server, \
|
void ConfigParser::_set_server_values(ServerConfig *server, \
|
||||||
const std::string key, std::string value)
|
const std::string key, std::string value)
|
||||||
{
|
{
|
||||||
@@ -189,11 +188,15 @@ void ConfigParser::_set_server_values(ServerConfig *server, \
|
|||||||
|
|
||||||
if (size < 1)
|
if (size < 1)
|
||||||
throw std::invalid_argument("missing value");
|
throw std::invalid_argument("missing value");
|
||||||
else if (key == "server_name" && size == 1)
|
else if (key == "server_name" && server->server_name.empty())
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < server->server_name.size(); i++)
|
// fuck should i be using an iterator?
|
||||||
|
// for (size_t i = 0; i < server->server_name.size(); i++)
|
||||||
|
for (std::vector<std::string>::iterator it = server->server_name.begin(); \
|
||||||
|
it < server->server_name.end(); it++)
|
||||||
{
|
{
|
||||||
if (server->server_name[i].compare(tmp_val[0]) == 0)
|
// if (server->server_name[i].compare(tmp_val[0]) == 0)
|
||||||
|
if (it->compare(tmp_val[0]) == 0)
|
||||||
throw std::invalid_argument("server_name already exists");
|
throw std::invalid_argument("server_name already exists");
|
||||||
}
|
}
|
||||||
server->server_name.push_back(tmp_val[0]);
|
server->server_name.push_back(tmp_val[0]);
|
||||||
@@ -229,12 +232,36 @@ void ConfigParser::_set_server_values(ServerConfig *server, \
|
|||||||
}
|
}
|
||||||
else if (key == "root" && size == 1 && server->root == "")
|
else if (key == "root" && size == 1 && server->root == "")
|
||||||
{
|
{
|
||||||
DIR* dir = opendir(tmp_val[0].c_str());
|
// consider using lstat if you don't? want symlinks included?
|
||||||
|
// don't bother with include <errno.h> for now.
|
||||||
|
// std::cout << tmp_val[0] << '\n';
|
||||||
|
|
||||||
|
// should i also check that it's not a file? no i think S_ISDIR does that right?
|
||||||
|
const char* folder = tmp_val[0].c_str();
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
if (stat(folder, &sb) == 0 && S_ISDIR(sb.st_mode))
|
||||||
|
{
|
||||||
|
// std::cout << "is a Dir\n";
|
||||||
|
server->root = tmp_val[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::invalid_argument("root dir could not be opened");
|
||||||
|
|
||||||
|
/* DIR* dir = opendir(tmp_val[0].c_str());
|
||||||
if (dir)
|
if (dir)
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
else
|
else
|
||||||
throw std::invalid_argument("root dir could not be opened");
|
{
|
||||||
server->root = tmp_val[0];
|
switch (errno) {
|
||||||
|
case EACCES: printf("Permission denied\n"); break;
|
||||||
|
case ENOENT: printf("Directory does not exist\n"); break;
|
||||||
|
case ENOTDIR: printf("is not a directory\n"); break;
|
||||||
|
default:
|
||||||
|
throw std::invalid_argument("root dir could not be opened 1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
else if (key == "autoindex" && size == 1)
|
else if (key == "autoindex" && size == 1)
|
||||||
{
|
{
|
||||||
@@ -258,14 +285,14 @@ void ConfigParser::_set_server_values(ServerConfig *server, \
|
|||||||
for (unsigned long i = 0; i != tmp_val.size(); i++)
|
for (unsigned long i = 0; i != tmp_val.size(); i++)
|
||||||
server->index.push_back(tmp_val[i]);
|
server->index.push_back(tmp_val[i]);
|
||||||
}
|
}
|
||||||
else if (key == "allow_methods" && server->allow_methods.empty())
|
else if (key == "allow_methods" && server->allow_methods == 0)
|
||||||
{
|
{
|
||||||
for (unsigned long i = 0; i != tmp_val.size(); i++)
|
for (unsigned long i = 0; i != tmp_val.size(); i++)
|
||||||
{
|
{
|
||||||
http_method m = ::str_to_http_method(tmp_val[i]);
|
http_method m = ::str_to_http_method(tmp_val[i]);
|
||||||
if (m == UNKNOWN)
|
if (m == UNKNOWN)
|
||||||
throw std::invalid_argument("not a valid method");
|
throw std::invalid_argument("not a valid method");
|
||||||
server->allow_methods.push_back(m);
|
server->allow_methods |= m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (key == "error_page")
|
else if (key == "error_page")
|
||||||
@@ -323,12 +350,16 @@ void ConfigParser::_set_location_values(LocationConfig *location, \
|
|||||||
throw std::invalid_argument("missing value");
|
throw std::invalid_argument("missing value");
|
||||||
else if (key == "root" && size == 1 && location->root == "")
|
else if (key == "root" && size == 1 && location->root == "")
|
||||||
{
|
{
|
||||||
DIR* dir = opendir(tmp_val[0].c_str());
|
const char* folder = tmp_val[0].c_str();
|
||||||
if (dir)
|
struct stat sb;
|
||||||
closedir(dir);
|
|
||||||
|
if (stat(folder, &sb) == 0 && S_ISDIR(sb.st_mode))
|
||||||
|
{
|
||||||
|
// std::cout << "is a Dir\n";
|
||||||
|
location->root = tmp_val[0];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
throw std::invalid_argument("root dir could not be opened");
|
throw std::invalid_argument("root dir could not be opened");
|
||||||
location->root = tmp_val[0];
|
|
||||||
}
|
}
|
||||||
else if (key == "client_body_limit" && size == 1 \
|
else if (key == "client_body_limit" && size == 1 \
|
||||||
&& location->client_body_limit == 0)
|
&& location->client_body_limit == 0)
|
||||||
@@ -343,14 +374,14 @@ void ConfigParser::_set_location_values(LocationConfig *location, \
|
|||||||
for (unsigned long i = 0; i != tmp_val.size(); i++)
|
for (unsigned long i = 0; i != tmp_val.size(); i++)
|
||||||
location->index.push_back(tmp_val[i]);
|
location->index.push_back(tmp_val[i]);
|
||||||
}
|
}
|
||||||
else if (key == "allow_methods" && location->allow_methods.empty())
|
else if (key == "allow_methods" && location->allow_methods == 0)
|
||||||
{
|
{
|
||||||
for (unsigned long i = 0; i != tmp_val.size(); i++)
|
for (unsigned long i = 0; i != tmp_val.size(); i++)
|
||||||
{
|
{
|
||||||
http_method m = ::str_to_http_method(tmp_val[i]);
|
http_method m = ::str_to_http_method(tmp_val[i]);
|
||||||
if (m == UNKNOWN)
|
if (m == UNKNOWN)
|
||||||
throw std::invalid_argument("not a valid method");
|
throw std::invalid_argument("not a valid method");
|
||||||
location->allow_methods.push_back(m);
|
location->allow_methods |= m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (key == "cgi_info")
|
else if (key == "cgi_info")
|
||||||
161
srcs/config/postProcessing.cpp
Normal file
161
srcs/config/postProcessing.cpp
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "ConfigParser.hpp"
|
||||||
|
|
||||||
|
// technically doesn't belong to ConfigParser or any other class
|
||||||
|
// adding static in front doesn't work...
|
||||||
|
/*
|
||||||
|
bool compareLocationConfigs(const LocationConfig &a, const LocationConfig &b)
|
||||||
|
{
|
||||||
|
int len_a;
|
||||||
|
int len_b;
|
||||||
|
size_t tmp = 0;
|
||||||
|
|
||||||
|
// consider adding 1 to path that ends in a file not folder.
|
||||||
|
|
||||||
|
|
||||||
|
while ((tmp = a.path.find_first_of("/", tmp)) != std::string::npos)
|
||||||
|
++len_a;
|
||||||
|
tmp = 0;
|
||||||
|
while ((tmp = b.path.find_first_of("/", tmp)) != std::string::npos)
|
||||||
|
++len_b;
|
||||||
|
return (len_a < len_b); // right comparison ? not <= ?
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ConfigParser::_post_processing(std::vector<ServerConfig> *servers)
|
||||||
|
{
|
||||||
|
|
||||||
|
// make certain servers default
|
||||||
|
// fill out empty settings
|
||||||
|
// if special settings are empty throw
|
||||||
|
|
||||||
|
std::vector<ServerConfig>::iterator it = servers->begin();
|
||||||
|
|
||||||
|
while (it != servers->end())
|
||||||
|
{
|
||||||
|
// host and port are Mandatory
|
||||||
|
if (it->host == "")
|
||||||
|
throw std::invalid_argument("Config file needs a host and port");
|
||||||
|
|
||||||
|
// root is mandatory
|
||||||
|
if (it->root == "")
|
||||||
|
throw std::invalid_argument("Config file needs a root");
|
||||||
|
|
||||||
|
if (it->client_body_limit == 0)
|
||||||
|
it->client_body_limit = 5000; // what is the recomended size?
|
||||||
|
|
||||||
|
// autoindex is False by Default
|
||||||
|
|
||||||
|
// if Allow methodes not specified we set to ALL
|
||||||
|
if (it->allow_methods == UNKNOWN) // in this case that means nothing...
|
||||||
|
it->allow_methods = ALL_METHODS;
|
||||||
|
|
||||||
|
if (it->index.empty())
|
||||||
|
throw std::invalid_argument("Config file needs an Index");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// if error_pages is left empty, we'll use the defaults which
|
||||||
|
// i believe are set elsewhere...
|
||||||
|
|
||||||
|
|
||||||
|
// actually do this at the end, once we know if there aren't any locations
|
||||||
|
// with path /
|
||||||
|
/* if (!_find_root_path_location(it->locations))
|
||||||
|
{
|
||||||
|
LocationConfig tmp;
|
||||||
|
|
||||||
|
tmp.path = "/";
|
||||||
|
tmp.client_body_limit = 5000; // figur out correct amount
|
||||||
|
tmp.root = it->root;
|
||||||
|
tmp.index = it->index;
|
||||||
|
tmp.allow_methods = it->allow_methods;
|
||||||
|
tmp.redirect_status = 0;
|
||||||
|
it->locations.push_back(tmp);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
std::vector<LocationConfig>::iterator it_l = it->locations.begin();
|
||||||
|
|
||||||
|
// first check locations we have
|
||||||
|
while (it_l != it->locations.end())
|
||||||
|
{
|
||||||
|
// opendir() doesn't work for some reason...
|
||||||
|
// this doens't work yet cuz the path needs to be relative and stat doesn't like / before...
|
||||||
|
/* const char* folder = it_l->path.c_str();
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
if (stat(folder, &sb) == 0 && S_ISDIR(sb.st_mode))
|
||||||
|
{
|
||||||
|
// std::cout << "is a Dir\n";
|
||||||
|
// it_l->path = it_lpath;
|
||||||
|
// yea nothing happens, i guess i can change how the if conditions work...
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::invalid_argument("location dir could not be opened");
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (it_l->client_body_limit == 0)
|
||||||
|
it_l->client_body_limit = 5000; // what is the recomended size?
|
||||||
|
if (it_l->root == "")
|
||||||
|
it_l->root = it->root;
|
||||||
|
|
||||||
|
// if Allow methodes not specified we set to Server methods
|
||||||
|
if (it_l->allow_methods == UNKNOWN) // in this case that means nothing...
|
||||||
|
it_l->allow_methods = it->allow_methods;
|
||||||
|
|
||||||
|
// fill out index from Server?
|
||||||
|
// or do a bunch of checks on what is in there...
|
||||||
|
if (it_l->index.empty())
|
||||||
|
it_l->index = it->index; // right?
|
||||||
|
|
||||||
|
// same for redirect status i think
|
||||||
|
|
||||||
|
// maybe do something for Cgi_info?
|
||||||
|
|
||||||
|
++it_l;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then put locations in order...
|
||||||
|
// may change how the order is set later
|
||||||
|
|
||||||
|
// ok we can sort in order and reverse...
|
||||||
|
|
||||||
|
std::cout << "made it to sorting...\n";
|
||||||
|
// std::sort(it->locations.begin(), it->locations.end(), compareLocationConfigs);
|
||||||
|
std::sort(it->locations.begin(), it->locations.end());
|
||||||
|
|
||||||
|
// for some reason no need to reverse...
|
||||||
|
// std::reverse(it->locations.begin(), it->locations.end());
|
||||||
|
|
||||||
|
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do the defaults at the end?
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConfigParser::_find_root_path_location(std::vector<LocationConfig> locations)
|
||||||
|
{
|
||||||
|
std::vector<LocationConfig>::iterator it = locations.begin();
|
||||||
|
|
||||||
|
while (it != locations.end())
|
||||||
|
{
|
||||||
|
if (it->path.compare("/") == 0)
|
||||||
|
{
|
||||||
|
std::cout << "in compare: " << it->path << " -- ";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -60,6 +60,8 @@ http_method str_to_http_method(std::string &str)
|
|||||||
return POST;
|
return POST;
|
||||||
else if (str == "DELETE")
|
else if (str == "DELETE")
|
||||||
return DELETE;
|
return DELETE;
|
||||||
|
else if (str == "ALL_METHODS")
|
||||||
|
return ALL_METHODS;
|
||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
# include <sstream>
|
# include <sstream>
|
||||||
# include <cstdlib> // atoi
|
# include <cstdlib> // atoi
|
||||||
|
|
||||||
|
|
||||||
// enum http_method
|
// enum http_method
|
||||||
// {
|
// {
|
||||||
// UNKNOWN = 0b00000000,
|
// UNKNOWN = 0b00000000,
|
||||||
@@ -33,4 +34,5 @@ std::string trim(std::string str, char c);
|
|||||||
http_method str_to_http_method(std::string &str);
|
http_method str_to_http_method(std::string &str);
|
||||||
std::string http_methods_to_str(unsigned int methods);
|
std::string http_methods_to_str(unsigned int methods);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
11
www/test/index.html
Normal file
11
www/test/index.html
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Le Webserv</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1 style="text-align:center">Le index (˘ ͜ʖ˘)</h1>
|
||||||
|
<hr>
|
||||||
|
<p style="text-align:center">(˚3˚)</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user