# Crow: /home/farook/cppsrv/crow-0.3-fordoc/include/crow/parser.h Source File

parser.h
#pragma once
#include <string>
#include <unordered_map>
#include <boost/algorithm/string.hpp>
#include <algorithm>
#include "crow/http_parser_merged.h"
#include "crow/http_request.h"
namespace crow
{
/// A wrapper for `nodejs/http-parser`.
/// Used to generate a \ref crow.request from the TCP socket buffer.
///
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->raw_url.insert(self->raw_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())
{
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())
{
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_);
// url params
self->url = self->raw_url.substr(0, self->raw_url.find("?"));
self->url_params = query_string(self->raw_url);
self->process_message();
return 0;
}
HTTPParser(Handler* handler) :
handler_(handler)
{
http_parser_init(this, HTTP_REQUEST);
}
// return false on error
/// Parse a buffer into the different sections of an HTTP request.
bool feed(const char* buffer, int length)
{
const static http_parser_settings settings_{
on_message_begin,
on_url,
nullptr,
on_header_field,
on_header_value,
on_headers_complete,
on_body,
on_message_complete,
};
int nparsed = http_parser_execute(this, &settings_, buffer, length);
return nparsed == length;
}
bool done()
{
return feed(nullptr, 0);
}
void clear()
{
url.clear();
raw_url.clear();
header_building_state = 0;
header_field.clear();
header_value.clear();
headers.clear();
url_params.clear();
body.clear();
}
void process_header()
{
handler_->handle_header();
}
void process_message()
{
handler_->handle();
}
/// Take the parsed HTTP request data and convert it to a \ref crow.request
request to_request() const
{
return request{static_cast<HTTPMethod>(method), std::move(raw_url), std::move(url), std::move(url_params), std::move(headers), std::move(body)};
}
bool is_upgrade() const
{
return upgrade;
}
bool check_version(int major, int minor) const
{
return http_major == major && http_minor == minor;
}
std::string raw_url;
std::string url;
int header_building_state = 0;
std::string header_field;
std::string header_value;
ci_map headers;
query_string url_params; ///< What comes after the `?` in the URL.
std::string body;
Handler* handler_; ///< This is currently an HTTP connection object (\ref crow.Connection).
};
}
crow::query_string
A class to represent any data coming after the ? in the request URL into key-value pairs.
Definition: query_string.h:292
crow::HTTPParser
A wrapper for nodejs/http-parser.
Definition: parser.h:19
crow::HTTPParser::to_request
request to_request() const
Take the parsed HTTP request data and convert it to a crow::request.
Definition: parser.h:146
crow::HTTPParser::handler_
Handler * handler_
This is currently an HTTP connection object (crow::Connection).
Definition: parser.h:171
crow::HTTPParser::feed
bool feed(const char *buffer, int length)
Parse a buffer into the different sections of an HTTP request.
Definition: parser.h:101
crow::HTTPParser::url_params
query_string url_params
What comes after the ? in the URL.
Definition: parser.h:168
crow::request
An HTTP request.
Definition: http_request.h:27