Removed unneeded code from http component

This commit is contained in:
Dennis Luxen 2010-07-26 12:27:58 +00:00
parent 7f63a84295
commit 2acad805b3
5 changed files with 401 additions and 580 deletions

View File

@ -136,7 +136,7 @@ private:
boost::array<char, 8192> buffer_; boost::array<char, 8192> buffer_;
/// The incoming request. /// The incoming request.
request request_; Request request_;
/// The parser for the incoming request. /// The parser for the incoming request.
request_parser request_parser_; request_parser request_parser_;

View File

@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt. or see http://www.gnu.org/licenses/agpl.txt.
*/ */
#ifndef HTTP_SERVER3_REPLY_HPP #ifndef HTTP_SERVER3_REPLY_HPP
@ -34,116 +34,50 @@ namespace http {
/// A reply to be sent to a client. /// A reply to be sent to a client.
struct reply struct reply
{ {
/// The status of the reply. /// The status of the reply.
enum status_type enum status_type
{ {
ok = 200, ok = 200,
created = 201, bad_request = 400,
accepted = 202, internal_server_error = 500
no_content = 204, } status;
multiple_choices = 300,
moved_permanently = 301,
moved_temporarily = 302,
not_modified = 304,
bad_request = 400,
unauthorized = 401,
forbidden = 403,
not_found = 404,
internal_server_error = 500,
not_implemented = 501,
bad_gateway = 502,
service_unavailable = 503
} status;
/// The headers to be included in the reply. std::vector<header> headers;
std::vector<header> headers;
/// The content to be sent in the reply. /// The content to be sent in the reply.
std::string content; std::string content;
/// Convert the reply into a vector of buffers. The buffers do not own the /// Convert the reply into a vector of buffers. The buffers do not own the
/// underlying memory blocks, therefore the reply object must remain valid and /// underlying memory blocks, therefore the reply object must remain valid and
/// not be changed until the write operation has completed. /// not be changed until the write operation has completed.
std::vector<boost::asio::const_buffer> to_buffers(); std::vector<boost::asio::const_buffer> to_buffers();
/// Get a stock reply. /// Get a stock reply.
static reply stock_reply(status_type status); static reply stock_reply(status_type status);
}; };
namespace status_strings { namespace status_strings {
const std::string ok = const std::string ok =
"HTTP/1.0 200 OK\r\n"; "HTTP/1.0 200 OK\r\n";
const std::string created =
"HTTP/1.0 201 Created\r\n";
const std::string accepted =
"HTTP/1.0 202 Accepted\r\n";
const std::string no_content =
"HTTP/1.0 204 No Content\r\n";
const std::string multiple_choices =
"HTTP/1.0 300 Multiple Choices\r\n";
const std::string moved_permanently =
"HTTP/1.0 301 Moved Permanently\r\n";
const std::string moved_temporarily =
"HTTP/1.0 302 Moved Temporarily\r\n";
const std::string not_modified =
"HTTP/1.0 304 Not Modified\r\n";
const std::string bad_request = const std::string bad_request =
"HTTP/1.0 400 Bad Request\r\n"; "HTTP/1.0 400 Bad Request\r\n";
const std::string unauthorized =
"HTTP/1.0 401 Unauthorized\r\n";
const std::string forbidden =
"HTTP/1.0 403 Forbidden\r\n";
const std::string not_found =
"HTTP/1.0 404 Not Found\r\n";
const std::string internal_server_error = const std::string internal_server_error =
"HTTP/1.0 500 Internal Server Error\r\n"; "HTTP/1.0 500 Internal Server Error\r\n";
const std::string not_implemented =
"HTTP/1.0 501 Not Implemented\r\n";
const std::string bad_gateway =
"HTTP/1.0 502 Bad Gateway\r\n";
const std::string service_unavailable =
"HTTP/1.0 503 Service Unavailable\r\n";
boost::asio::const_buffer to_buffer(reply::status_type status) boost::asio::const_buffer to_buffer(reply::status_type status)
{ {
switch (status) switch (status)
{ {
case reply::ok: case reply::ok:
return boost::asio::buffer(ok); return boost::asio::buffer(ok);
case reply::created: case reply::bad_request:
return boost::asio::buffer(created); return boost::asio::buffer(bad_request);
case reply::accepted: case reply::internal_server_error:
return boost::asio::buffer(accepted); return boost::asio::buffer(internal_server_error);
case reply::no_content: default:
return boost::asio::buffer(no_content); return boost::asio::buffer(bad_request);
case reply::multiple_choices: }
return boost::asio::buffer(multiple_choices);
case reply::moved_permanently:
return boost::asio::buffer(moved_permanently);
case reply::moved_temporarily:
return boost::asio::buffer(moved_temporarily);
case reply::not_modified:
return boost::asio::buffer(not_modified);
case reply::bad_request:
return boost::asio::buffer(bad_request);
case reply::unauthorized:
return boost::asio::buffer(unauthorized);
case reply::forbidden:
return boost::asio::buffer(forbidden);
case reply::not_found:
return boost::asio::buffer(not_found);
case reply::internal_server_error:
return boost::asio::buffer(internal_server_error);
case reply::not_implemented:
return boost::asio::buffer(not_implemented);
case reply::bad_gateway:
return boost::asio::buffer(bad_gateway);
case reply::service_unavailable:
return boost::asio::buffer(service_unavailable);
default:
return boost::asio::buffer(internal_server_error);
}
} }
} // namespace status_strings } // namespace status_strings
@ -157,154 +91,63 @@ const char crlf[] = { '\r', '\n' };
std::vector<boost::asio::const_buffer> reply::to_buffers() std::vector<boost::asio::const_buffer> reply::to_buffers()
{ {
std::vector<boost::asio::const_buffer> buffers; std::vector<boost::asio::const_buffer> buffers;
buffers.push_back(status_strings::to_buffer(status)); buffers.push_back(status_strings::to_buffer(status));
for (std::size_t i = 0; i < headers.size(); ++i) for (std::size_t i = 0; i < headers.size(); ++i)
{ {
header& h = headers[i]; header& h = headers[i];
buffers.push_back(boost::asio::buffer(h.name)); buffers.push_back(boost::asio::buffer(h.name));
buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator)); buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator));
buffers.push_back(boost::asio::buffer(h.value)); buffers.push_back(boost::asio::buffer(h.value));
buffers.push_back(boost::asio::buffer(misc_strings::crlf)); buffers.push_back(boost::asio::buffer(misc_strings::crlf));
} }
buffers.push_back(boost::asio::buffer(misc_strings::crlf)); buffers.push_back(boost::asio::buffer(misc_strings::crlf));
buffers.push_back(boost::asio::buffer(content)); buffers.push_back(boost::asio::buffer(content));
return buffers; return buffers;
} }
namespace stock_replies { namespace stock_replies {
const char ok[] = ""; const char ok[] = "";
const char created[] =
"<html>"
"<head><title>Created</title></head>"
"<body><h1>201 Created</h1></body>"
"</html>";
const char accepted[] =
"<html>"
"<head><title>Accepted</title></head>"
"<body><h1>202 Accepted</h1></body>"
"</html>";
const char no_content[] =
"<html>"
"<head><title>No Content</title></head>"
"<body><h1>204 Content</h1></body>"
"</html>";
const char multiple_choices[] =
"<html>"
"<head><title>Multiple Choices</title></head>"
"<body><h1>300 Multiple Choices</h1></body>"
"</html>";
const char moved_permanently[] =
"<html>"
"<head><title>Moved Permanently</title></head>"
"<body><h1>301 Moved Permanently</h1></body>"
"</html>";
const char moved_temporarily[] =
"<html>"
"<head><title>Moved Temporarily</title></head>"
"<body><h1>302 Moved Temporarily</h1></body>"
"</html>";
const char not_modified[] =
"<html>"
"<head><title>Not Modified</title></head>"
"<body><h1>304 Not Modified</h1></body>"
"</html>";
const char bad_request[] = const char bad_request[] =
"<html>" "<html>"
"<head><title>Bad Request</title></head>" "<head><title>Bad Request</title></head>"
"<body><h1>400 Bad Request</h1></body>" "<body><h1>400 Bad Request</h1></body>"
"</html>"; "</html>";
const char unauthorized[] =
"<html>"
"<head><title>Unauthorized</title></head>"
"<body><h1>401 Unauthorized</h1></body>"
"</html>";
const char forbidden[] =
"<html>"
"<head><title>Forbidden</title></head>"
"<body><h1>403 Forbidden</h1></body>"
"</html>";
const char not_found[] =
"<html>"
"<head><title>Not Found</title></head>"
"<body><h1>404 Not Found</h1></body>"
"</html>";
const char internal_server_error[] = const char internal_server_error[] =
"<html>" "<html>"
"<head><title>Internal Server Error</title></head>" "<head><title>Internal Server Error</title></head>"
"<body><h1>500 Internal Server Error</h1></body>" "<body><h1>500 Internal Server Error</h1></body>"
"</html>"; "</html>";
const char not_implemented[] =
"<html>"
"<head><title>Not Implemented</title></head>"
"<body><h1>501 Not Implemented</h1></body>"
"</html>";
const char bad_gateway[] =
"<html>"
"<head><title>Bad Gateway</title></head>"
"<body><h1>502 Bad Gateway</h1></body>"
"</html>";
const char service_unavailable[] =
"<html>"
"<head><title>Service Unavailable</title></head>"
"<body><h1>503 Service Unavailable</h1></body>"
"</html>";
std::string to_string(reply::status_type status) std::string to_string(reply::status_type status)
{ {
switch (status) switch (status)
{ {
case reply::ok: case reply::ok:
return ok; return ok;
case reply::created: case reply::bad_request:
return created; return bad_request;
case reply::accepted: case reply::internal_server_error:
return accepted; return internal_server_error;
case reply::no_content: default:
return no_content; return internal_server_error;
case reply::multiple_choices: }
return multiple_choices;
case reply::moved_permanently:
return moved_permanently;
case reply::moved_temporarily:
return moved_temporarily;
case reply::not_modified:
return not_modified;
case reply::bad_request:
return bad_request;
case reply::unauthorized:
return unauthorized;
case reply::forbidden:
return forbidden;
case reply::not_found:
return not_found;
case reply::internal_server_error:
return internal_server_error;
case reply::not_implemented:
return not_implemented;
case reply::bad_gateway:
return bad_gateway;
case reply::service_unavailable:
return service_unavailable;
default:
return internal_server_error;
}
} }
} // namespace stock_replies } // namespace stock_replies
reply reply::stock_reply(reply::status_type status) reply reply::stock_reply(reply::status_type status)
{ {
reply rep; reply rep;
rep.status = status; rep.status = status;
rep.content = stock_replies::to_string(status); rep.content = stock_replies::to_string(status);
rep.headers.resize(2); rep.headers.resize(2);
rep.headers[0].name = "Content-Length"; rep.headers[0].name = "Content-Length";
rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size()); rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size());
rep.headers[1].name = "Content-Type"; rep.headers[1].name = "Content-Type";
rep.headers[1].value = "text/html"; rep.headers[1].value = "text/html";
return rep; return rep;
} }
} // namespace http } // namespace http

View File

@ -16,25 +16,21 @@ You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt. or see http://www.gnu.org/licenses/agpl.txt.
*/ */
#ifndef HTTP_REQUEST_HPP #ifndef HTTP_REQUEST_HPP
#define HTTP_REQUEST_HPP #define HTTP_REQUEST_HPP
#include <string> #include <string>
#include <vector> #include <list>
#include "header.h" #include "header.h"
namespace http { namespace http {
/// A request received from a client. /// A request received from a client.
struct request struct Request
{ {
std::string method; std::string uri;
std::string uri;
int http_version_major;
int http_version_minor;
std::vector<header> headers;
}; };
} }

View File

@ -36,7 +36,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
namespace http { namespace http {
struct reply; struct reply;
struct request; struct Request;
/// The common handler for all incoming requests. /// The common handler for all incoming requests.
template<typename GraphT> template<typename GraphT>
@ -47,7 +47,7 @@ public:
explicit request_handler(SearchEngine<EdgeData, GraphT> * s) : sEngine(s){} explicit request_handler(SearchEngine<EdgeData, GraphT> * s) : sEngine(s){}
/// Handle a request and produce a reply. /// Handle a request and produce a reply.
void handle_request(const request& req, reply& rep){ void handle_request(const Request& req, reply& rep){
try { try {
std::string request(req.uri); std::string request(req.uri);
std::string command; std::string command;
@ -152,7 +152,7 @@ public:
rep.headers[2].value = "attachment; filename=\"route.kml\""; rep.headers[2].value = "attachment; filename=\"route.kml\"";
return; return;
} }
rep = reply::stock_reply(reply::not_found); rep = reply::stock_reply(reply::bad_request);
return; return;
} catch(std::exception& e) } catch(std::exception& e)
{ {

View File

@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt. or see http://www.gnu.org/licenses/agpl.txt.
*/ */
#ifndef HTTP_REQUEST_PARSER_HPP #ifndef HTTP_REQUEST_PARSER_HPP
@ -27,77 +27,77 @@ or see http://www.gnu.org/licenses/agpl.txt.
namespace http { namespace http {
struct request; struct Request;
/// Parser for incoming requests. /// Parser for incoming requests.
class request_parser class request_parser
{ {
public: public:
/// Construct ready to parse the request method. /// Construct ready to parse the request method.
request_parser(); request_parser();
/// Reset to initial parser state. /// Reset to initial parser state.
void reset(); void reset();
/// Parse some data. The tribool return value is true when a complete request /// Parse some data. The tribool return value is true when a complete request
/// has been parsed, false if the data is invalid, indeterminate when more /// has been parsed, false if the data is invalid, indeterminate when more
/// data is required. The InputIterator return value indicates how much of the /// data is required. The InputIterator return value indicates how much of the
/// input has been consumed. /// input has been consumed.
template <typename InputIterator> template <typename InputIterator>
boost::tuple<boost::tribool, InputIterator> parse(request& req, boost::tuple<boost::tribool, InputIterator> parse(Request& req,
InputIterator begin, InputIterator end) InputIterator begin, InputIterator end)
{ {
while (begin != end) while (begin != end)
{ {
boost::tribool result = consume(req, *begin++); boost::tribool result = consume(req, *begin++);
if (result || !result) if (result || !result)
return boost::make_tuple(result, begin); return boost::make_tuple(result, begin);
} }
boost::tribool result = boost::indeterminate; boost::tribool result = boost::indeterminate;
return boost::make_tuple(result, begin); return boost::make_tuple(result, begin);
} }
private: private:
/// Handle the next character of input. /// Handle the next character of input.
boost::tribool consume(request& req, char input); boost::tribool consume(Request& req, char input);
/// Check if a byte is an HTTP character. /// Check if a byte is an HTTP character.
static bool is_char(int c); static bool is_char(int c);
/// Check if a byte is an HTTP control character. /// Check if a byte is an HTTP control character.
static bool is_ctl(int c); static bool is_ctl(int c);
/// Check if a byte is defined as an HTTP tspecial character. /// Check if a byte is defined as an HTTP tspecial character.
static bool is_tspecial(int c); static bool is_tspecial(int c);
/// Check if a byte is a digit. /// Check if a byte is a digit.
static bool is_digit(int c); static bool is_digit(int c);
/// The current state of the parser. /// The current state of the parser.
enum state enum state
{ {
method_start, method_start,
method, method,
uri_start, uri_start,
uri, uri,
http_version_h, http_version_h,
http_version_t_1, http_version_t_1,
http_version_t_2, http_version_t_2,
http_version_p, http_version_p,
http_version_slash, http_version_slash,
http_version_major_start, http_version_major_start,
http_version_major, http_version_major,
http_version_minor_start, http_version_minor_start,
http_version_minor, http_version_minor,
expecting_newline_1, expecting_newline_1,
header_line_start, header_line_start,
header_lws, header_lws,
header_name, header_name,
space_before_header_value, space_before_header_value,
header_value, header_value,
expecting_newline_2, expecting_newline_2,
expecting_newline_3 expecting_newline_3
} state_; } state_;
}; };
@ -108,311 +108,293 @@ private:
namespace http { namespace http {
request_parser::request_parser() request_parser::request_parser()
: state_(method_start) : state_(method_start)
{ {
} }
void request_parser::reset() void request_parser::reset()
{ {
state_ = method_start; state_ = method_start;
} }
boost::tribool request_parser::consume(request& req, char input) boost::tribool request_parser::consume(Request& req, char input)
{ {
switch (state_) switch (state_)
{ {
case method_start: case method_start:
if (!is_char(input) || is_ctl(input) || is_tspecial(input)) if (!is_char(input) || is_ctl(input) || is_tspecial(input))
{ {
return false; return false;
} }
else else
{ {
state_ = method; state_ = method;
req.method.push_back(input); return boost::indeterminate;
return boost::indeterminate; }
} case method:
case method: if (input == ' ')
if (input == ' ') {
{ state_ = uri;
state_ = uri; return boost::indeterminate;
return boost::indeterminate; }
} else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
{ return false;
return false; }
} else
else {
{ return boost::indeterminate;
req.method.push_back(input); }
return boost::indeterminate; case uri_start:
} if (is_ctl(input))
case uri_start: {
if (is_ctl(input)) return false;
{ }
return false; else
} {
else state_ = uri;
{ req.uri.push_back(input);
state_ = uri; return boost::indeterminate;
req.uri.push_back(input); }
return boost::indeterminate; case uri:
} if (input == ' ')
case uri: {
if (input == ' ') state_ = http_version_h;
{ return boost::indeterminate;
state_ = http_version_h; }
return boost::indeterminate; else if (is_ctl(input))
} {
else if (is_ctl(input)) return false;
{ }
return false; else
} {
else req.uri.push_back(input);
{ return boost::indeterminate;
req.uri.push_back(input); }
return boost::indeterminate; case http_version_h:
} if (input == 'H')
case http_version_h: {
if (input == 'H') state_ = http_version_t_1;
{ return boost::indeterminate;
state_ = http_version_t_1; }
return boost::indeterminate; else
} {
else return false;
{ }
return false; case http_version_t_1:
} if (input == 'T')
case http_version_t_1: {
if (input == 'T') state_ = http_version_t_2;
{ return boost::indeterminate;
state_ = http_version_t_2; }
return boost::indeterminate; else
} {
else return false;
{ }
return false; case http_version_t_2:
} if (input == 'T')
case http_version_t_2: {
if (input == 'T') state_ = http_version_p;
{ return boost::indeterminate;
state_ = http_version_p; }
return boost::indeterminate; else
} {
else return false;
{ }
return false; case http_version_p:
} if (input == 'P')
case http_version_p: {
if (input == 'P') state_ = http_version_slash;
{ return boost::indeterminate;
state_ = http_version_slash; }
return boost::indeterminate; else
} {
else return false;
{ }
return false; case http_version_slash:
} if (input == '/')
case http_version_slash: {
if (input == '/') state_ = http_version_major_start;
{ return boost::indeterminate;
req.http_version_major = 0; }
req.http_version_minor = 0; else
state_ = http_version_major_start; {
return boost::indeterminate; return false;
} }
else case http_version_major_start:
{ if (is_digit(input))
return false; {
} state_ = http_version_major;
case http_version_major_start: return boost::indeterminate;
if (is_digit(input)) }
{ else
req.http_version_major = req.http_version_major * 10 + input - '0'; {
state_ = http_version_major; return false;
return boost::indeterminate; }
} case http_version_major:
else if (input == '.')
{ {
return false; state_ = http_version_minor_start;
} return boost::indeterminate;
case http_version_major: }
if (input == '.') else if (is_digit(input))
{ {
state_ = http_version_minor_start; return boost::indeterminate;
return boost::indeterminate; }
} else
else if (is_digit(input)) {
{ return false;
req.http_version_major = req.http_version_major * 10 + input - '0'; }
return boost::indeterminate; case http_version_minor_start:
} if (is_digit(input))
else {
{ state_ = http_version_minor;
return false; return boost::indeterminate;
} }
case http_version_minor_start: else
if (is_digit(input)) {
{ return false;
req.http_version_minor = req.http_version_minor * 10 + input - '0'; }
state_ = http_version_minor; case http_version_minor:
return boost::indeterminate; if (input == '\r')
} {
else state_ = expecting_newline_1;
{ return boost::indeterminate;
return false; }
} else if (is_digit(input))
case http_version_minor: {
if (input == '\r') return boost::indeterminate;
{ }
state_ = expecting_newline_1; else
return boost::indeterminate; {
} return false;
else if (is_digit(input)) }
{ case expecting_newline_1:
req.http_version_minor = req.http_version_minor * 10 + input - '0'; if (input == '\n')
return boost::indeterminate; {
} state_ = header_line_start;
else return boost::indeterminate;
{ }
return false; else
} {
case expecting_newline_1: return false;
if (input == '\n') }
{ case header_line_start:
state_ = header_line_start; if (input == '\r')
return boost::indeterminate; {
} state_ = expecting_newline_3;
else return boost::indeterminate;
{ }
return false; else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
} {
case header_line_start: return false;
if (input == '\r') }
{ else
state_ = expecting_newline_3; {
return boost::indeterminate; state_ = header_name;
} return boost::indeterminate;
else if (!req.headers.empty() && (input == ' ' || input == '\t')) }
{ case header_lws:
state_ = header_lws; if (input == '\r')
return boost::indeterminate; {
} state_ = expecting_newline_2;
else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) return boost::indeterminate;
{ }
return false; else if (input == ' ' || input == '\t')
} {
else return boost::indeterminate;
{ }
req.headers.push_back(header()); else if (is_ctl(input))
req.headers.back().name.push_back(input); {
state_ = header_name; return false;
return boost::indeterminate; }
} else
case header_lws: {
if (input == '\r') state_ = header_value;
{ return boost::indeterminate;
state_ = expecting_newline_2; }
return boost::indeterminate; case header_name:
} if (input == ':')
else if (input == ' ' || input == '\t') {
{ state_ = space_before_header_value;
return boost::indeterminate; return boost::indeterminate;
} }
else if (is_ctl(input)) else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
{ {
return false; return false;
} }
else else
{ {
state_ = header_value; return boost::indeterminate;
req.headers.back().value.push_back(input); }
return boost::indeterminate; case space_before_header_value:
} if (input == ' ')
case header_name: {
if (input == ':') state_ = header_value;
{ return boost::indeterminate;
state_ = space_before_header_value; }
return boost::indeterminate; else
} {
else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) return false;
{ }
return false; case header_value:
} if (input == '\r')
else {
{ state_ = expecting_newline_2;
req.headers.back().name.push_back(input); return boost::indeterminate;
return boost::indeterminate; }
} else if (is_ctl(input))
case space_before_header_value: {
if (input == ' ') return false;
{ }
state_ = header_value; else
return boost::indeterminate; {
} return boost::indeterminate;
else }
{ case expecting_newline_2:
return false; if (input == '\n')
} {
case header_value: state_ = header_line_start;
if (input == '\r') return boost::indeterminate;
{ }
state_ = expecting_newline_2; else
return boost::indeterminate; {
} return false;
else if (is_ctl(input)) }
{ case expecting_newline_3:
return false; return (input == '\n');
} default:
else return false;
{ }
req.headers.back().value.push_back(input);
return boost::indeterminate;
}
case expecting_newline_2:
if (input == '\n')
{
state_ = header_line_start;
return boost::indeterminate;
}
else
{
return false;
}
case expecting_newline_3:
return (input == '\n');
default:
return false;
}
} }
bool request_parser::is_char(int c) bool request_parser::is_char(int c)
{ {
return c >= 0 && c <= 127; return c >= 0 && c <= 127;
} }
bool request_parser::is_ctl(int c) bool request_parser::is_ctl(int c)
{ {
return (c >= 0 && c <= 31) || (c == 127); return (c >= 0 && c <= 31) || (c == 127);
} }
bool request_parser::is_tspecial(int c) bool request_parser::is_tspecial(int c)
{ {
switch (c) switch (c)
{ {
case '(': case ')': case '<': case '>': case '@': case '(': case ')': case '<': case '>': case '@':
case ',': case ';': case ':': case '\\': case '"': case ',': case ';': case ':': case '\\': case '"':
case '/': case '[': case ']': case '?': case '=': case '/': case '[': case ']': case '?': case '=':
case '{': case '}': case ' ': case '\t': case '{': case '}': case ' ': case '\t':
return true; return true;
default: default:
return false; return false;
} }
} }
bool request_parser::is_digit(int c) bool request_parser::is_digit(int c)
{ {
return c >= '0' && c <= '9'; return c >= '0' && c <= '9';
} }
} // namespace http } // namespace http