aboutsummaryrefslogtreecommitdiffstats
path: root/include/parser.h
diff options
context:
space:
mode:
authoripknHama <ipknhama@gmail.com>2014-08-07 01:18:33 +0900
committeripknHama <ipknhama@gmail.com>2014-08-07 01:18:33 +0900
commit031615ac866cc3c8f1900dd4b4aae2106ad31230 (patch)
treeb8b7206ffbd2043368580ec269c97436929fe452 /include/parser.h
parenta0c93f5b84cc11b30bc6320ac26127832ef8bf7a (diff)
downloadcrow-031615ac866cc3c8f1900dd4b4aae2106ad31230.tar.gz
crow-031615ac866cc3c8f1900dd4b4aae2106ad31230.zip
source resturcturing + CMake
Diffstat (limited to 'include/parser.h')
-rw-r--r--include/parser.h154
1 files changed, 154 insertions, 0 deletions
diff --git a/include/parser.h b/include/parser.h
new file mode 100644
index 0000000..f504248
--- /dev/null
+++ b/include/parser.h
@@ -0,0 +1,154 @@
+#pragma once
+
+#include <string>
+#include <unordered_map>
+#include <boost/algorithm/string.hpp>
+
+#include "http_request.h"
+
+namespace crow
+{
+ template <typename Handler>
+ struct HTTPParser : public http_parser
+ {
+ static int on_message_begin(http_parser* self_)
+ {
+ HTTPParser* self = static_cast<HTTPParser*>(self_);
+ self->clear();
+ return 0;
+ }
+ static int on_url(http_parser* self_, const char* at, size_t length)
+ {
+ HTTPParser* self = static_cast<HTTPParser*>(self_);
+ self->url.insert(self->url.end(), at, at+length);
+ return 0;
+ }
+ static int on_header_field(http_parser* self_, const char* at, size_t length)
+ {
+ HTTPParser* self = static_cast<HTTPParser*>(self_);
+ switch (self->header_building_state)
+ {
+ case 0:
+ if (!self->header_value.empty())
+ {
+ boost::algorithm::to_lower(self->header_field);
+ self->headers.emplace(std::move(self->header_field), std::move(self->header_value));
+ }
+ self->header_field.assign(at, at+length);
+ self->header_building_state = 1;
+ break;
+ case 1:
+ self->header_field.insert(self->header_field.end(), at, at+length);
+ break;
+ }
+ return 0;
+ }
+ static int on_header_value(http_parser* self_, const char* at, size_t length)
+ {
+ HTTPParser* self = static_cast<HTTPParser*>(self_);
+ switch (self->header_building_state)
+ {
+ case 0:
+ self->header_value.insert(self->header_value.end(), at, at+length);
+ break;
+ case 1:
+ self->header_building_state = 0;
+ self->header_value.assign(at, at+length);
+ break;
+ }
+ return 0;
+ }
+ static int on_headers_complete(http_parser* self_)
+ {
+ HTTPParser* self = static_cast<HTTPParser*>(self_);
+ if (!self->header_field.empty())
+ {
+ boost::algorithm::to_lower(self->header_field);
+ self->headers.emplace(std::move(self->header_field), std::move(self->header_value));
+ }
+ self->process_header();
+ return 0;
+ }
+ static int on_body(http_parser* self_, const char* at, size_t length)
+ {
+ HTTPParser* self = static_cast<HTTPParser*>(self_);
+ self->body.insert(self->body.end(), at, at+length);
+ return 0;
+ }
+ static int on_message_complete(http_parser* self_)
+ {
+ HTTPParser* self = static_cast<HTTPParser*>(self_);
+ self->process_message();
+ return 0;
+ }
+ HTTPParser(Handler* handler) :
+ settings_ {
+ on_message_begin,
+ on_url,
+ nullptr,
+ on_header_field,
+ on_header_value,
+ on_headers_complete,
+ on_body,
+ on_message_complete,
+ },
+ handler_(handler)
+ {
+ http_parser_init(this, HTTP_REQUEST);
+ }
+
+ // return false on error
+ bool feed(const char* buffer, int length)
+ {
+ int nparsed = http_parser_execute(this, &settings_, buffer, length);
+ return nparsed == length;
+ }
+
+ bool done()
+ {
+ int nparsed = http_parser_execute(this, &settings_, nullptr, 0);
+ return nparsed == 0;
+ }
+
+ void clear()
+ {
+ url.clear();
+ header_building_state = 0;
+ header_field.clear();
+ header_value.clear();
+ headers.clear();
+ body.clear();
+ }
+
+ void process_header()
+ {
+ handler_->handle_header();
+ }
+
+ void process_message()
+ {
+ handler_->handle();
+ }
+
+ request to_request() const
+ {
+ return request{(HTTPMethod)method, std::move(url), std::move(headers), std::move(body)};
+ }
+
+ bool check_version(int major, int minor) const
+ {
+ return http_major == major && http_minor == minor;
+ }
+
+ std::string url;
+ int header_building_state = 0;
+ std::string header_field;
+ std::string header_value;
+ std::unordered_map<std::string, std::string> headers;
+ std::string body;
+
+ http_parser_settings settings_;
+
+ Handler* handler_;
+ };
+}