-
Notifications
You must be signed in to change notification settings - Fork 0
/
http.hpp
197 lines (169 loc) · 5.09 KB
/
http.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#ifndef HTTP_HPP
#define HTTP_HPP
#include <string>
#include <vector>
#include <map>
#include <ctime>
namespace http {
std::string time_to_string (std::string const& fmt);
std::string time_to_string (std::string const& fmt, std::time_t epoch);
std::time_t time_decode (std::string const& fmt, std::string const& datime);
struct simple_token_type {
std::string token;
void clear () { token.clear (); }
bool equal_token (std::string const& name) const { return token == name; }
bool operator == (simple_token_type const& x) const { return token == x.token; }
};
struct token_type {
std::string token;
std::vector<std::string> parameter;
void clear () { token.clear (); parameter.clear (); }
bool equal_token (std::string const& name) const { return token == name; }
bool operator == (token_type const& x) const
{
return token == x.token && parameter == x.parameter;
}
};
struct content_length_type {
int status;
ssize_t length;
bool operator == (content_length_type const& x) const
{
return status == x.status && length == x.length;
}
};
struct etag_type {
bool weak;
std::string opaque;
etag_type () : weak (false), opaque () {}
etag_type (bool const w, std::string const& o) { weak = w; opaque = o; }
void clear () { weak = false; opaque.clear (); }
bool empty () const { return opaque.empty (); }
bool equal_weak (etag_type const& x)
{
return opaque == x.opaque;
}
bool equal_strong (etag_type const& x)
{
return ! weak && ! x.weak && opaque == x.opaque;
}
bool operator == (etag_type const& x) const
{
return weak == x.weak && opaque == x.opaque;
}
};
class condition_type {
public:
enum {FAILED, OK};
condition_type (etag_type const& et, std::time_t tm)
: etag (et), mtime (tm) {}
int check (std::string const& method, std::map<std::string, std::string>& header);
private:
etag_type etag;
std::time_t mtime;
int if_match (std::string const& field);
int if_none_match (std::string const& field);
int if_unmodified_since (std::string const& field);
int if_modified_since (std::string const& field);
};
struct request_type {
std::string method;
std::string uri;
std::string http_version;
std::map<std::string, std::string> header;
ssize_t content_length;
std::string body;
void clear ();
};
struct response_type {
int code;
std::string http_version;
std::map<std::string, std::string> header;
ssize_t content_length;
std::string body;
int body_fd;
bool has_body;
bool chunked;
ssize_t chunk_size;
std::string statuscode () const;
std::string to_string ();
void clear ();
};
template<class T>
std::size_t index (std::vector<T>& fields, std::string const& name)
{
for (std::size_t i = 0; i < fields.size (); ++i)
if (fields[i].equal_token (name))
return i;
return fields.size ();
}
bool decode (std::vector<simple_token_type>& fields, std::string const& src, int const lowerlimit);
bool decode (std::vector<token_type>& fields, std::string const& src, int const lowerlimit);
bool decode (content_length_type& field, std::string const& src);
bool decode (std::vector<etag_type>& fields, std::string const& src);
class decoder_request_line_type {
public:
decoder_request_line_type ();
void set_limit_nbyte (std::size_t const x) { limit_nbyte = x; }
bool put (uint32_t const octet, request_type& req);
void clear ();
bool good () const;
bool bad () const;
bool partial () const;
private:
std::size_t limit_nbyte;
int next_state;
std::size_t nbyte;
bool failure () { next_state = 0; return false; }
};
class decoder_request_header_type {
public:
decoder_request_header_type ();
void set_limit_nfield (std::size_t const x) { limit_nfield = x; }
void set_limit_nbyte (std::size_t const x) { limit_nbyte = x; }
bool put (uint32_t const octet, request_type& req);
void clear ();
bool good () const;
bool bad () const;
bool partial () const;
private:
int next_state;
std::string name;
std::string value;
std::string spaces;
std::size_t nfield;
std::size_t nbyte;
std::size_t limit_nfield;
std::size_t limit_nbyte;
bool failure () { next_state = 0; return false; }
};
class decoder_chunk_type {
public:
enum {CHUNK_SIZE_LIMIT = 1024*1024};
int chunk_size_limit;
ssize_t content_length;
int chunk_size;
decoder_chunk_type ();
bool put (int c, std::string& body);
void clear ();
bool good () const;
bool bad () const;
bool partial () const;
private:
int next_state;
};
class logger_type {
public:
static logger_type& getinstance ();
void put_error (std::string const& s);
void put_error (std::string const& ho, std::string const& s);
void put_info (std::string const& s);
void put (std::string const& ho, request_type& req, response_type& res);
private:
logger_type ();
~logger_type ();
logger_type (logger_type const&);
logger_type& operator= (logger_type const&);
};
}//namespace http
#endif