aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoripknHama <ipknhama@gmail.com>2014-04-01 01:51:50 +0900
committeripknHama <ipknhama@gmail.com>2014-04-01 01:51:50 +0900
commit4b8c67e2300205200f4f846400d73a03cb3da854 (patch)
tree46b63650efd6952cf88a62cc0511162af54d896f
parent1e11a177ee6b680b55f01d6090ccd1b2e2b8c51c (diff)
downloadcrow-4b8c67e2300205200f4f846400d73a03cb3da854.tar.gz
crow-4b8c67e2300205200f4f846400d73a03cb3da854.zip
accept connections, print http request parsed information
-rw-r--r--.gitmodules3
-rw-r--r--Makefile8
-rw-r--r--example.cpp10
-rw-r--r--flask.h31
m---------http-parser0
-rw-r--r--http_connection.h48
-rw-r--r--http_server.h48
-rw-r--r--parser.h79
-rw-r--r--test.py3
9 files changed, 227 insertions, 3 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..95da8a7
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "http-parser"]
+ path = http-parser
+ url = https://github.com/joyent/http-parser
diff --git a/Makefile b/Makefile
index bc09577..66d35d5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,7 @@
all: example
-example: example.cpp
- g++ -o example example.cpp
+example: example.cpp flask.h http_server.h http_connection.h parser.h
+ g++ -g -std=c++11 -o example example.cpp http-parser/http_parser.c -pthread -lboost_system -lboost_thread -I http-parser/
+test: example
+ ./example &
+ test.py
+ pkill example
diff --git a/example.cpp b/example.cpp
index 3b07d61..904e1ff 100644
--- a/example.cpp
+++ b/example.cpp
@@ -1,8 +1,16 @@
#include "flask.h"
+#include <iostream>
+
flask::Flask app;
int main()
{
- app.run();
+ app.route("/",
+ []{
+ return "Hello World!";
+ });
+
+ app.port(8080)
+ .run();
}
diff --git a/flask.h b/flask.h
index ff134f7..c694de1 100644
--- a/flask.h
+++ b/flask.h
@@ -1,3 +1,15 @@
+#pragma once
+#include <string>
+#include <functional>
+#include <memory>
+#include <future>
+#include <stdint.h>
+
+#include "http_server.h"
+
+// TEST
+#include <iostream>
+
namespace flask
{
class Flask
@@ -7,8 +19,27 @@ namespace flask
{
}
+ void handle()
+ {
+ }
+
+ void route(const std::string& url, std::function<std::string()> f)
+ {
+ }
+
+ Flask& port(std::uint16_t port)
+ {
+ port_ = port;
+ return *this;
+ }
+
void run()
{
+ Server<Flask> server(this, port_);
+ server.run();
}
+ private:
+ uint16_t port_ = 80;
};
};
+
diff --git a/http-parser b/http-parser
new file mode 160000
+Subproject d19e12911a1b523885bdf0d82f1f3e91df90711
diff --git a/http_connection.h b/http_connection.h
new file mode 100644
index 0000000..92b06e1
--- /dev/null
+++ b/http_connection.h
@@ -0,0 +1,48 @@
+#pragma once
+#include <boost/asio.hpp>
+#include <http_parser.h>
+#include "parser.h"
+
+namespace flask
+{
+ using namespace boost;
+ using tcp = asio::ip::tcp;
+ template <typename Handler>
+ class Connection
+ {
+ public:
+ Connection(tcp::socket&& socket, Handler* handler) : socket_(std::move(socket)), handler_(handler)
+ {
+ }
+
+ void start()
+ {
+ do_read();
+ }
+
+ private:
+ void do_read()
+ {
+ socket_.async_read_some(boost::asio::buffer(buffer_),
+ [this](boost::system::error_code ec, std::size_t bytes_transferred)
+ {
+ if (!ec)
+ {
+ parser_.feed(buffer_.data(), bytes_transferred);
+ }
+ else
+ {
+ parser_.done();
+ }
+ });
+ }
+
+ private:
+ tcp::socket socket_;
+ Handler* handler_;
+
+ std::array<char, 8192> buffer_;
+
+ HTTPParser parser_;
+ };
+}
diff --git a/http_server.h b/http_server.h
new file mode 100644
index 0000000..002eec6
--- /dev/null
+++ b/http_server.h
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <boost/asio.hpp>
+#include <stdint.h>
+
+#include "http_connection.h"
+
+// TEST
+#include <iostream>
+
+namespace flask
+{
+ using namespace boost;
+ using tcp = asio::ip::tcp;
+ template <typename Handler>
+ class Server
+ {
+ public:
+ Server(Handler* handler, uint16_t port)
+ : acceptor_(io_service_, tcp::endpoint(asio::ip::address(), port)), socket_(io_service_), handler_(handler)
+ {
+ do_accept();
+ }
+
+ void run()
+ {
+ auto _ = std::async(std::launch::async, [this]{io_service_.run();});
+ }
+
+ private:
+ void do_accept()
+ {
+ acceptor_.async_accept(socket_,
+ [this](boost::system::error_code ec)
+ {
+ if (!ec)
+ (new Connection<Handler>(std::move(socket_), handler_))->start();
+ do_accept();
+ });
+ }
+
+ private:
+ asio::io_service io_service_;
+ tcp::acceptor acceptor_;
+ tcp::socket socket_;
+ Handler* handler_;
+ };
+}
diff --git a/parser.h b/parser.h
new file mode 100644
index 0000000..2f2626d
--- /dev/null
+++ b/parser.h
@@ -0,0 +1,79 @@
+#include <iostream>
+#include <string>
+namespace flask
+{
+ struct HTTPParser : public http_parser
+ {
+ static int on_message_begin(http_parser* self_)
+ {
+ HTTPParser* self = static_cast<HTTPParser*>(self_);
+ return 0;
+ }
+ static int on_url(http_parser* self_, const char* at, size_t length)
+ {
+ HTTPParser* self = static_cast<HTTPParser*>(self_);
+ std::cout << std::string(at, at+length) << std::endl;
+ return 0;
+ }
+ static int on_status(http_parser* self_, const char* at, size_t length)
+ {
+ HTTPParser* self = static_cast<HTTPParser*>(self_);
+ std::cout << std::string(at, at+length) << std::endl;
+ return 0;
+ }
+ static int on_header_field(http_parser* self_, const char* at, size_t length)
+ {
+ HTTPParser* self = static_cast<HTTPParser*>(self_);
+ std::cout << std::string(at, at+length) << std::endl;
+ return 0;
+ }
+ static int on_header_value(http_parser* self_, const char* at, size_t length)
+ {
+ HTTPParser* self = static_cast<HTTPParser*>(self_);
+ std::cout << std::string(at, at+length) << std::endl;
+ return 0;
+ }
+ static int on_headers_complete(http_parser* self_)
+ {
+ HTTPParser* self = static_cast<HTTPParser*>(self_);
+ return 0;
+ }
+ static int on_body(http_parser* self_, const char* at, size_t length)
+ {
+ HTTPParser* self = static_cast<HTTPParser*>(self_);
+ std::cout << std::string(at, at+length) << std::endl;
+ return 0;
+ }
+ static int on_message_complete(http_parser* self_)
+ {
+ HTTPParser* self = static_cast<HTTPParser*>(self_);
+ return 0;
+ }
+ HTTPParser() :
+ settings_ {
+ on_message_begin,
+ on_url,
+ on_status,
+ on_header_field,
+ on_header_value,
+ on_headers_complete,
+ on_body,
+ on_message_complete,
+ }
+ {
+ http_parser_init(this, HTTP_REQUEST);
+ }
+
+ void feed(const char* buffer, int length)
+ {
+ int nparsed = http_parser_execute(this, &settings_, buffer, length);
+ }
+
+ void done()
+ {
+ int nparsed = http_parser_execute(this, &settings_, nullptr, 0);
+ }
+
+ http_parser_settings settings_;
+ };
+}
diff --git a/test.py b/test.py
new file mode 100644
index 0000000..49b7368
--- /dev/null
+++ b/test.py
@@ -0,0 +1,3 @@
+import urllib
+d = urllib.urlopen('http://localhost:8080').read()
+print d