4#include "http_parser.h"
9#include <unordered_map>
17 inline http_header(std::string n, std::string v)
18 : name(std::move(n)), value(std::move(v)) {
20 inline bool is(
const char* s,
size_t len)
const {
21 return name.length() == len && memcmp(name.data(), s, len) == 0;
23 inline bool is(
const std::string& s)
const {
24 return is(s.data(), s.length());
26 static inline bool equals_canonical(
const char* s1,
const char* s2,
size_t len) {
27 const char* end2 = s2 + len;
28 for (; s2 != end2; ++s1, ++s2)
30 && (*s1 <
'A' || *s1 >
'Z' || (*s1 -
'A' +
'a') != *s2))
34 static inline bool equals_canonical(
const std::string& str,
const char* s,
size_t len) {
35 return str.length() == len && equals_canonical(str.data(), s, len);
37 inline bool is_canonical(
const char* s,
size_t len)
const {
38 return equals_canonical(name, s, len);
40 inline bool is_canonical(
const std::string& s)
const {
41 return is_canonical(s.data(), s.length());
43 inline bool is_content_length()
const {
44 return is_canonical(
"content-length", 14);
50 typedef std::vector<http_header>::const_iterator header_iterator;
52 inline http_message();
54 inline bool ok()
const;
55 inline bool operator!()
const;
56 inline enum http_errno error()
const;
58 inline unsigned http_major()
const;
59 inline unsigned http_minor()
const;
61 inline unsigned status_code()
const;
62 inline const std::string& status_message()
const;
63 inline enum http_method method()
const;
64 inline const std::string& url()
const;
65 inline bool has_canonical_header(
const char* name,
size_t length)
const;
66 inline bool has_canonical_header(
const char* name)
const;
67 inline bool has_canonical_header(
const std::string& name)
const;
68 header_iterator find_canonical_header(
const char* name,
size_t length)
const;
69 inline header_iterator find_canonical_header(
const char* name)
const;
70 inline header_iterator find_canonical_header(
const std::string& name)
const;
71 std::string canonical_header(
const char* name,
size_t length)
const;
72 inline std::string canonical_header(
const char* name)
const;
73 inline std::string canonical_header(
const std::string& name)
const;
74 inline bool has_header(
const std::string& name)
const;
75 inline header_iterator find_header(
const std::string& name)
const;
76 inline std::string header(
const std::string& name)
const;
77 inline const std::string& body()
const;
79 std::string host()
const;
80 inline std::string url_schema()
const;
81 inline std::string url_host()
const;
82 std::string url_host_port()
const;
83 uint16_t url_port()
const;
84 inline std::string url_path()
const;
85 inline bool has_query()
const;
86 inline std::string query()
const;
87 bool has_query(
const std::string& name)
const;
88 std::string query(
const std::string& name)
const;
90 inline header_iterator header_begin()
const;
91 inline header_iterator header_end()
const;
92 inline header_iterator query_begin()
const;
93 inline header_iterator query_end()
const;
95 inline http_message& clear();
96 void add_header(std::string key, std::string value);
98 inline http_message& http_major(
unsigned v);
99 inline http_message& http_minor(
unsigned v);
100 inline http_message& error(
enum http_errno e);
101 inline http_message& status_code(
unsigned code);
102 inline http_message& status_code(
unsigned code, std::string message);
103 inline http_message& method(
enum http_method method);
104 inline http_message& url(std::string url);
105 inline http_message& header(std::string key, std::string value);
106 inline http_message& header(std::string key,
size_t value);
107 inline http_message& date_header(std::string key, time_t value);
108 inline http_message& body(std::string body);
109 inline http_message& append_body(
const std::string& x);
111 static std::string canonicalize(std::string x);
112 static const char* default_status_message(
unsigned code);
116 info_url = 1, info_query = 2
121 struct http_parser_url urlp;
122 std::vector<http_header> raw_query;
128 unsigned short major_;
129 unsigned short minor_;
130 unsigned status_code_ : 16;
131 unsigned method_ : 8;
133 unsigned upgrade_ : 1;
136 std::string status_message_;
137 std::vector<http_header> raw_headers_;
140 mutable std::shared_ptr<info_type> info_;
142 inline void kill_info(
unsigned f)
const;
143 inline info_type& info(
unsigned f)
const;
144 void make_info(
unsigned f)
const;
145 inline bool has_url_field(
int field)
const;
146 inline std::string url_field(
int field)
const;
148 friend class http_parser;
153 http_parser(
enum http_parser_type type);
156 inline bool ok()
const;
157 inline enum http_errno error()
const;
158 inline bool should_keep_alive()
const;
160 void receive(fd f, event<http_message> done);
161 void send(fd f,
const http_message& m, event<> done);
162 static void send_request(fd f,
const http_message& m, event<> done);
163 static void send_request(fd f, http_message&& m, event<> done);
164 static void send_response(fd f,
const http_message& m, event<> done);
165 static void send_response(fd f, http_message&& m, event<> done);
166 static void send_response_headers(fd f,
const http_message& m, event<> done);
167 static void send_response_chunk(fd f, std::string s, event<> done);
168 static void send_response_end(fd f, event<> done);
170 inline void clear_should_keep_alive();
175 struct message_data {
178 std::ostringstream sbuf;
182 static const http_parser_settings settings;
183 static http_parser* get_parser(::http_parser* hp);
184 static message_data* get_message_data(::http_parser* hp);
185 static int on_message_begin(::http_parser* hp);
186 static int on_url(::http_parser* hp,
const char* s,
size_t len);
187 static int on_status(::http_parser* hp,
const char* s,
size_t len);
188 static int on_header_field(::http_parser* hp,
const char* s,
size_t len);
189 static int on_header_value(::http_parser* hp,
const char* s,
size_t len);
190 static int on_headers_complete(::http_parser* hp);
191 static int on_body(::http_parser* hp,
const char* s,
size_t len);
192 static int on_message_complete(::http_parser* hp);
193 inline void copy_parser_status(message_data& md);
194 static void unparse_request_headers(std::ostringstream& buf,
195 const http_message& m);
196 static void unparse_response_headers(std::ostringstream& buf,
197 const http_message& m,
198 bool include_content_length);
199 static inline std::string prepare_headers(
const http_message& m,
202 static inline void send_message(fd f, std::string headers,
203 std::string body, event<> done);
204 static void send_two(fd f, std::string a, std::string b, event<> done);
206 class closure__receive__2fdQ12http_message_;
void receive(closure__receive__2fdQ12http_message_&);
207 class closure__send_response_chunk__2fdSsQ_;
static void send_response_chunk(closure__send_response_chunk__2fdSsQ_&);
208 class closure__send_two__2fdSsSsQ_;
static void send_two(closure__send_two__2fdSsSsQ_&);
211inline http_message::http_message()
212 : major_(1), minor_(1), status_code_(200), method_(HTTP_GET),
213 error_(HPE_OK), upgrade_(0) {
216inline void http_message::kill_info(
unsigned f)
const {
221inline unsigned http_message::http_major()
const {
225inline unsigned http_message::http_minor()
const {
229inline bool http_message::ok()
const {
230 return error_ == HPE_OK;
233inline bool http_message::operator!()
const {
237inline enum http_errno http_message::error()
const {
238 return (
enum http_errno) error_;
241inline unsigned http_message::status_code()
const {
245inline const std::string& http_message::status_message()
const {
246 return status_message_;
249inline enum http_method http_message::method()
const {
250 return (
enum http_method) method_;
253inline const std::string& http_message::url()
const {
257inline bool http_message::has_canonical_header(
const char* name,
size_t length)
const {
258 return find_canonical_header(name, length) != header_end();
261inline bool http_message::has_canonical_header(
const char* name)
const {
262 return find_canonical_header(name) != header_end();
265inline bool http_message::has_canonical_header(
const std::string& name)
const {
266 return find_canonical_header(name) != header_end();
269inline http_message::header_iterator http_message::find_canonical_header(
const char* name)
const {
270 return find_canonical_header(name, strlen(name));
273inline http_message::header_iterator http_message::find_canonical_header(
const std::string& name)
const {
274 return find_canonical_header(name.data(), name.length());
277inline std::string http_message::canonical_header(
const char* name)
const {
278 return canonical_header(name, strlen(name));
281inline std::string http_message::canonical_header(
const std::string& name)
const {
282 return canonical_header(name.data(), name.length());
285inline bool http_message::has_header(
const std::string& name)
const {
286 return has_canonical_header(canonicalize(name));
289inline http_message::header_iterator http_message::find_header(
const std::string& name)
const {
290 return find_canonical_header(canonicalize(name));
293inline std::string http_message::header(
const std::string& name)
const {
294 return canonical_header(canonicalize(name));
297inline const std::string& http_message::body()
const {
301inline bool http_message::has_url_field(
int field)
const {
302 return info(info_url).urlp.field_set & (1 << field);
305inline std::string http_message::url_field(
int field)
const {
306 const info_type& i = info(info_url);
307 if (i.urlp.field_set & (1 << field))
308 return url_.substr(i.urlp.field_data[field].off,
309 i.urlp.field_data[field].len);
311 return std::string();
314inline bool http_message::has_query()
const {
315 return has_url_field(UF_QUERY);
318inline std::string http_message::query()
const {
319 return url_field(UF_QUERY);
322inline std::string http_message::url_schema()
const {
323 return url_field(UF_SCHEMA);
326inline std::string http_message::url_host()
const {
327 return url_field(UF_HOST);
330inline std::string http_message::url_path()
const {
331 return url_field(UF_PATH);
334inline http_message& http_message::http_major(
unsigned v) {
339inline http_message& http_message::http_minor(
unsigned v) {
344inline http_message& http_message::clear() {
349inline http_message& http_message::error(
enum http_errno e) {
354inline http_message& http_message::status_code(
unsigned code) {
356 status_message_ = std::string();
360inline http_message& http_message::status_code(
unsigned code, std::string message) {
362 status_message_ = std::move(message);
366inline http_message& http_message::method(
enum http_method method) {
367 method_ = (unsigned) method;
371inline http_message& http_message::url(std::string url) {
372 url_ = std::move(url);
373 kill_info(info_url | info_query);
377inline http_message& http_message::header(std::string key, std::string value) {
378 add_header(std::move(key), std::move(value));
382inline http_message& http_message::header(std::string key,
size_t value) {
383 std::ostringstream buf;
385 add_header(std::move(key), buf.str());
389inline http_message& http_message::date_header(std::string key, time_t value) {
392 strftime(buf,
sizeof(buf),
"%a, %d %b %Y %H:%M:%S GMT", gmtime(&value));
393 add_header(std::move(key), std::string(buf));
397inline http_message& http_message::body(std::string body) {
398 body_ = std::move(body);
402inline http_message& http_message::append_body(
const std::string& x) {
407inline http_message::info_type& http_message::info(
unsigned f)
const {
408 if (!info_ || !info_.unique() || (info_->flags & f) != f)
413inline http_message::header_iterator http_message::header_begin()
const {
414 return raw_headers_.begin();
417inline http_message::header_iterator http_message::header_end()
const {
418 return raw_headers_.end();
421inline http_message::header_iterator http_message::query_begin()
const {
422 return info(info_query).raw_query.begin();
425inline http_message::header_iterator http_message::query_end()
const {
426 return info(info_query).raw_query.end();
429inline bool http_parser::ok()
const {
430 return hp_.http_errno == (unsigned) HPE_OK;
433inline enum http_errno http_parser::error()
const {
434 return (
enum http_errno) hp_.http_errno;
437inline bool http_parser::should_keep_alive()
const {
438 return http_should_keep_alive(&hp_);
441inline void http_parser::clear_should_keep_alive() {
442 hp_.flags = (hp_.flags & ~F_CONNECTION_KEEP_ALIVE) | F_CONNECTION_CLOSE;
445inline void http_parser::send_message(fd f, std::string headers,
446 std::string body, event<> done) {
448 f.write(headers, done);
450 send_two(f, headers, body, done);
Definition rendezvous.hh:463
Event-based file descriptor wrapper class.
Namespace containing public Tamer classes and functions for the Tamer core.
Definition adapter.hh:17