-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathConfiguration.hpp
153 lines (131 loc) · 5.37 KB
/
Configuration.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include "Directive.hpp"
#include "Logger.hpp"
class Configuration {
public:
Configuration(std::ifstream &config_file, const Logger& logger);
~Configuration();
const Directive& getHttpDirective( void ) const;
std::vector<Directive>::const_iterator getDirectiveIterator( void ) const;
std::vector<Directive>::const_iterator getDirectiveEnd( void ) const;
std::vector<Directive>::iterator getDirectiveMutableIterator( void );
std::vector<Directive>::iterator getDirectiveMutableEnd( void );
void validate(const Logger& logger);
private:
std::vector<Directive> directives;
Logger l;
// Additional stuff we need in the configuration
public:
// Configuration exceptions are parsing errors, invalid syntax or
// directives that will not allow us to continue.
class Exception : public std::exception {
private:
const std::string _message;
public:
Exception(const std::string& reason, int line, const std::string& context) :
_message("Config error on line " + std::to_string(line) + " : "
+ reason + " ( " + context + " )") { }
Exception(const std::string& reason, int line) :
_message("Config error on line " + std::to_string(line) + " : " + reason) { }
Exception(const std::string& reason) :
_message("Config error : " + reason) { }
Exception(const std::string& reason, const std::string& context) :
_message("Config error : " + reason + " ( " + context + " )") { }
virtual const char* what() const throw() {
return _message.c_str();
}
};
// Map of directive strings with a vector of allowed subdirectives under
// it. Empty string means root directive.
//
// This is also an exhaustive list
// of directives, so if a directive string is not in this map, it is
// not recognized by us and should throw an error.
static const inline std::unordered_map<std::string, std::vector<std::string>> allowed_directives = {
{"", {"http", "log_level"}},
{"autoindex", {}},
{"client_max_body_size", {}},
{"error_page", {}},
{"http", {"autoindex", "client_max_body_size",
"error_page", "index", "root", "server", "upload_dir"}},
{"index", {}},
{"limit_except", {}},
{"listen", {}},
{"upload_dir", {}},
{"location", {"autoindex", "client_max_body_size",
"error_page", "index", "limit_except",
"location", "return", "root", "upload_dir"}},
{"log_level", {}},
{"return", {}},
{"root", {}},
{"server", {"autoindex", "client_max_body_size",
"error_page", "index", "listen", "location",
"return", "root", "server_name", "upload_dir"}},
{"server_name", {}},
};
// Vector of directives that cannot have more than one
// in the given context. The second one will throw an exception.
static const inline std::vector<std::string> unique_in_context = {
"autoindex",
"client_max_body_size",
"http",
"index",
"limit_except",
"log_level",
"return",
"root"
};
// Map of directive strings with an integer if the directive has a
// minimum number of arguments.
static const inline std::unordered_map<std::string, int> argument_min = {
{"autoindex", 1},
{"client_max_body_size", 1},
{"error_page", 2},
{"index", 1},
{"limit_except", 1},
{"listen", 1},
{"location", 1},
{"log_level", 1},
{"return", 1},
{"root", 1},
{"server_name", 1}
};
// Map of directive strings with an integer if the directive has a
// maximum number of arguments.
static const inline std::unordered_map<std::string, int> argument_max = {
{"autoindex", 1},
{"client_max_body_size", 1},
{"http", 0},
{"log_level", 1},
{"return", 2},
{"root", 1},
{"server", 0}
};
// Map of directive strings with a vector describing its allowed arguments
// If a directive is not in this map, it allows arbitrary arguments
static const inline std::unordered_map<std::string, std::vector<std::string>> allowed_arguments = {
{"autoindex", {"on", "off"}, },
{"limit_except", {"GET", "POST", "DELETE"}, },
{"log_level", {"debug", "info", "warning", "error"} },
};
// Map of directive strings with a member function pointer for a
// validator to call on them, in case their arguments have requirements
// not covered by the standard checks performed in here.
//
// Value has to be a pointer to a const member function of the Directive
// class that takes a const reference to the config logger and
// returns nothing. This function is expected to throw a
// Configuration::Exception if its arguments are invalid.
typedef void (Directive::*validator)( const Logger& ) const;
static const inline std::unordered_map<std::string, validator> arg_validators = {
{"client_max_body_size", &Directive::client_max_body_size_validator },
{"error_page", &Directive::error_page_validator },
{"return", &Directive::return_validator },
};
};