summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2010-12-30 22:30:23 +0100
committerVegard Storheil Eriksen <zyp@jvnv.net>2010-12-30 22:30:23 +0100
commit2e2221b2eda1c089688b3e87b42b0dc6720f6c59 (patch)
tree4cde9a917494bce8ea15c33acebbfffb34d60711
parent757edd54cca1d3bc19617284bba5d008a976f704 (diff)
Added request parser based on Boost.Spirit.
-rw-r--r--http_connection.cpp61
-rw-r--r--http_connection.h23
2 files changed, 81 insertions, 3 deletions
diff --git a/http_connection.cpp b/http_connection.cpp
index 36c0f00..fb45aac 100644
--- a/http_connection.cpp
+++ b/http_connection.cpp
@@ -4,9 +4,10 @@
#include "music.h"
#include <boost/bind.hpp>
-#include <boost/algorithm/string/split.hpp>
-#include <boost/algorithm/string/classification.hpp>
-#include <boost/algorithm/string/predicate.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
+namespace qi = boost::spirit::qi;
HTTP::Connection::Connection(boost::asio::io_service& io_service) : socket(io_service) {
}
@@ -15,7 +16,30 @@ void HTTP::Connection::handle_write(const boost::system::error_code& error, size
}
void HTTP::Connection::handle_read(const boost::system::error_code& error, size_t bytes_transferred) {
+ if(!parse_request(buf)) {
+ // Request parse error.
+ return;
+ }
+
+ std::cout << "Path: " << std::endl;
+ for(std::vector<std::string>::iterator it = path.begin(); it != path.end(); it++) {
+ std::cout << " " << *it << std::endl;
+ }
+
+ std::cout << "Args: " << std::endl;
+ for(std::map<std::string, std::string>::iterator it = args.begin(); it != args.end(); it++) {
+ std::cout << " " << it->first << " = " << it->second << std::endl;
+ }
+
+ std::cout << "Headers: " << std::endl;
+ for(std::map<std::string, std::string>::iterator it = headers.begin(); it != headers.end(); it++) {
+ std::cout << " " << it->first << " = " << it->second << std::endl;
+ }
+
+ return;
+
std::istream is(&buf);
+
HTTPRequest req(is);
HTTPResponse res(socket);
@@ -32,6 +56,37 @@ void HTTP::Connection::handle_read(const boost::system::error_code& error, size_
}
}
+void print(char c) {
+ std::cout << "Char: " << int(c) << std::endl;
+}
+
+bool HTTP::Connection::parse_request(boost::asio::streambuf& buf) {
+ typedef boost::asio::buffers_iterator<boost::asio::streambuf::const_buffers_type> Iterator;
+
+ Iterator begin = Iterator::begin(buf.data());
+ Iterator end = Iterator::end(buf.data());
+
+ qi::rule<Iterator, std::string()> word_p = +(qi::char_ - ' ' - '\r');
+
+ qi::rule<Iterator, std::vector<std::string>()> path_p = '/' >> +(qi::char_ - '/' - '?' - ' ') % '/';
+
+ qi::rule<Iterator, std::pair<std::string, std::string>()> pair_p = +(qi::char_ - '=') >> '=' >> +(qi::char_ - '&' - ' ');
+ qi::rule<Iterator, std::map<std::string, std::string>()> args_p = '?' >> pair_p >> *('&' >> pair_p);
+
+ qi::rule<Iterator, std::pair<std::string, std::string>()> header_p = +(qi::char_ - ':') >> ": " >> +(qi::char_ - '\r');
+ qi::rule<Iterator, std::map<std::string, std::string>()> headers_p = *(header_p >> "\r\n");
+
+ return qi::parse(begin, end,
+ // Method, path, args, version:
+ word_p >> ' ' >> path_p >> -args_p >> ' ' >> word_p >> "\r\n" >>
+ // Headers:
+ headers_p >>
+ // End of headers:
+ "\r\n",
+ // Store into:
+ method, path, args, version, headers);
+}
+
void HTTP::Connection::start() {
boost::asio::async_read_until(socket, buf, "\r\n\r\n", boost::bind(&Connection::handle_read, shared_from_this(),
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
diff --git a/http_connection.h b/http_connection.h
index f166f44..b6d6e27 100644
--- a/http_connection.h
+++ b/http_connection.h
@@ -1,6 +1,10 @@
#ifndef HTTP_CONNECTION_H
#define HTTP_CONNECTION_H
+#include <string>
+#include <vector>
+#include <map>
+
#include <boost/asio.hpp>
#include <boost/enable_shared_from_this.hpp>
using boost::asio::ip::tcp;
@@ -15,6 +19,25 @@ namespace HTTP {
void handle_read(const boost::system::error_code& error, size_t bytes_transferred);
tcp::socket socket;
boost::asio::streambuf buf;
+
+ //! Request method.
+ std::string method;
+
+ //! Request path.
+ std::vector<std::string> path;
+
+ //! Request arguments.
+ std::map<std::string, std::string> args;
+
+ //! Request version.
+ std::string version;
+
+ //! Request headers.
+ std::map<std::string, std::string> headers;
+
+
+ //! Parse request headers.
+ bool parse_request(boost::asio::streambuf& buf);
public:
typedef boost::shared_ptr<Connection> p;