aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authoripknHama <ipknhama@gmail.com>2014-09-07 04:30:53 +0900
committeripknHama <ipknhama@gmail.com>2014-09-07 04:30:53 +0900
commit2748e35430b9a4aaf64dfbd626d819f0fc5eedd2 (patch)
treea8ebd5648d46cc7073b2ae6f6b5ada0e702c456c /include
parentc89cafa820ec02f041c3b0e52877bc321f6a1ba9 (diff)
downloadcrow-2748e35430b9a4aaf64dfbd626d819f0fc5eedd2.tar.gz
crow-2748e35430b9a4aaf64dfbd626d819f0fc5eedd2.zip
basic middleware test: before_handler
Diffstat (limited to 'include')
-rw-r--r--include/crow.h16
-rw-r--r--include/http_connection.h64
-rw-r--r--include/http_request.h2
-rw-r--r--include/http_response.h13
-rw-r--r--include/http_server.h11
-rw-r--r--include/middleware.h15
6 files changed, 98 insertions, 23 deletions
diff --git a/include/crow.h b/include/crow.h
index a018f31..a4b82df 100644
--- a/include/crow.h
+++ b/include/crow.h
@@ -13,12 +13,9 @@
#include "http_server.h"
#include "utility.h"
#include "routing.h"
-#include "middleware_impl.h"
+#include "middleware_context.h"
#include "http_request.h"
-// TEST
-#include <iostream>
-
#define CROW_ROUTE(app, url) app.route<crow::black_magic::get_parameter_tag(url)>(url)
namespace crow
@@ -28,13 +25,14 @@ namespace crow
{
public:
using self_t = Crow;
+ using server_t = Server<Crow, Middlewares...>;
Crow()
{
}
void handle(const request& req, response& res)
{
- return router_.handle(req, res);
+ router_.handle(req, res);
}
template <uint64_t Tag>
@@ -71,7 +69,7 @@ namespace crow
void run()
{
validate();
- Server<self_t> server(this, port_, concurrency_);
+ server_t server(this, port_, concurrency_);
server.run();
}
@@ -84,19 +82,17 @@ namespace crow
// middleware
using context_t = detail::context<Middlewares...>;
template <typename T>
- T& get_middleware_context(request& req)
+ typename T::context& get_middleware_context(const request& req)
{
static_assert(black_magic::contains<T, Middlewares...>::value, "App doesn't have the specified middleware type.");
auto& ctx = *reinterpret_cast<context_t*>(req.middleware_context);
- return ctx.get<T>();
+ return ctx.template get<T>();
}
private:
uint16_t port_ = 80;
uint16_t concurrency_ = 1;
- std::tuple<Middlewares...> middlewares_;
-
Router router_;
};
template <typename ... Middlewares>
diff --git a/include/http_connection.h b/include/http_connection.h
index 907485f..a8631d9 100644
--- a/include/http_connection.h
+++ b/include/http_connection.h
@@ -2,9 +2,9 @@
#include <boost/asio.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/lexical_cast.hpp>
+#include <boost/array.hpp>
#include <atomic>
#include <chrono>
-#include <array>
#include "http_parser_merged.h"
@@ -14,23 +14,57 @@
#include "logging.h"
#include "settings.h"
#include "dumb_timer_queue.h"
+#include "middleware_context.h"
namespace crow
{
+ namespace detail
+ {
+ template <int N, typename Context, typename Container, typename CurrentMW, typename ... Middlewares>
+ bool middleware_call_helper(Container& middlewares, request& req, response& res, Context& ctx)
+ {
+ // TODO cut ctx to partial_context<0..N-1>
+ std::get<N>(middlewares).before_handle(req, res, ctx.template get<CurrentMW>(), ctx);
+ if (res.is_completed())
+ {
+ std::get<N>(middlewares).after_handle(req, res, ctx.template get<CurrentMW>(), ctx);
+ return true;
+ }
+ if (middleware_call_helper<N+1, Context, Middlewares...>(middlewares, req, res, ctx))
+ {
+ std::get<N>(middlewares).after_handle(req, res, ctx.template get<CurrentMW>(), ctx);
+ return true;
+ }
+ return false;
+ }
+
+ template <int N, typename Context, typename Container>
+ bool middleware_call_helper(Container& middlewares, request& req, response& res, Context& ctx)
+ {
+ return false;
+ }
+ }
+
using namespace boost;
using tcp = asio::ip::tcp;
#ifdef CROW_ENABLE_DEBUG
static int connectionCount;
#endif
- template <typename Handler>
+ template <typename Handler, typename ... Middlewares>
class Connection
{
public:
- Connection(boost::asio::io_service& io_service, Handler* handler, const std::string& server_name)
+ Connection(
+ boost::asio::io_service& io_service,
+ Handler* handler,
+ const std::string& server_name,
+ std::tuple<Middlewares...>& middlewares
+ )
: socket_(io_service),
handler_(handler),
parser_(this),
- server_name_(server_name)
+ server_name_(server_name),
+ middlewares_(middlewares)
{
#ifdef CROW_ENABLE_DEBUG
connectionCount ++;
@@ -101,11 +135,20 @@ namespace crow
<< method_name(req.method) << " " << req.url;
+ need_to_call_after_handlers_ = false;
if (!is_invalid_request)
{
res.complete_request_handler_ = [this]{ this->complete_request(); };
res.is_alive_helper_ = [this]()->bool{ return socket_.is_open(); };
- handler_->handle(req, res);
+
+ req.middleware_context = (void*)&ctx_;
+ detail::middleware_call_helper<0, decltype(ctx_), decltype(middlewares_), Middlewares...>(middlewares_, req, res, ctx_);
+
+ if (!res.completed_)
+ {
+ need_to_call_after_handlers_ = true;
+ handler_->handle(req, res);
+ }
}
else
{
@@ -117,6 +160,11 @@ namespace crow
{
CROW_LOG_INFO << "Response: " << this << ' ' << res.code << ' ' << close_connection_;
+ if (need_to_call_after_handlers_)
+ {
+ // TODO call all of after_handlers
+ }
+
//auto self = this->shared_from_this();
res.complete_request_handler_ = nullptr;
@@ -330,7 +378,7 @@ namespace crow
tcp::socket socket_;
Handler* handler_;
- std::array<char, 4096> buffer_;
+ boost::array<char, 4096> buffer_;
HTTPParser<Connection> parser_;
response res;
@@ -348,6 +396,10 @@ namespace crow
bool is_reading{};
bool is_writing{};
+ bool need_to_call_after_handlers_;
+
+ std::tuple<Middlewares...>& middlewares_;
+ detail::context<Middlewares...> ctx_;
};
}
diff --git a/include/http_request.h b/include/http_request.h
index 77b3ecb..af623c6 100644
--- a/include/http_request.h
+++ b/include/http_request.h
@@ -11,6 +11,6 @@ namespace crow
std::unordered_map<std::string, std::string> headers;
std::string body;
- void* middleware_context;
+ void* middleware_context{};
};
}
diff --git a/include/http_response.h b/include/http_response.h
index ae92543..bc468b7 100644
--- a/include/http_response.h
+++ b/include/http_response.h
@@ -5,11 +5,11 @@
namespace crow
{
- template <typename T>
+ template <typename Handler, typename ... Middlewares>
class Connection;
struct response
{
- template <typename T>
+ template <typename Handler, typename ... Middlewares>
friend class crow::Connection;
std::string body;
@@ -31,7 +31,7 @@ namespace crow
response& operator = (const response& r) = delete;
- response& operator = (response&& r)
+ response& operator = (response&& r) noexcept
{
body = std::move(r.body);
json_value = std::move(r.json_value);
@@ -41,6 +41,11 @@ namespace crow
return *this;
}
+ bool is_completed() const noexcept
+ {
+ return completed_;
+ }
+
void clear()
{
body.clear();
@@ -59,11 +64,11 @@ namespace crow
{
if (!completed_)
{
- completed_ = true;
if (complete_request_handler_)
{
complete_request_handler_();
}
+ completed_ = true;
}
}
diff --git a/include/http_server.h b/include/http_server.h
index 6dc845a..484aa83 100644
--- a/include/http_server.h
+++ b/include/http_server.h
@@ -18,7 +18,7 @@ namespace crow
using namespace boost;
using tcp = asio::ip::tcp;
- template <typename Handler>
+ template <typename Handler, typename ... Middlewares>
class Server
{
public:
@@ -43,10 +43,13 @@ namespace crow
for(uint16_t i = 0; i < concurrency_; i ++)
v.push_back(
std::async(std::launch::async, [this, i]{
+ // initializing timer queue
auto& timer_queue = detail::dumb_timer_queue::get_current_dumb_timer_queue();
+
timer_queue.set_io_service(*io_service_pool_[i]);
boost::asio::deadline_timer timer(*io_service_pool_[i]);
timer.expires_from_now(boost::posix_time::seconds(1));
+
std::function<void(const boost::system::error_code& ec)> handler;
handler = [&](const boost::system::error_code& ec){
if (ec)
@@ -56,6 +59,7 @@ namespace crow
timer.async_wait(handler);
};
timer.async_wait(handler);
+
io_service_pool_[i]->run();
}));
CROW_LOG_INFO << server_name_ << " server is running, local port " << port_;
@@ -92,7 +96,7 @@ namespace crow
void do_accept()
{
- auto p = new Connection<Handler>(pick_io_service(), handler_, server_name_);
+ auto p = new Connection<Handler, Middlewares...>(pick_io_service(), handler_, server_name_, middlewares_);
acceptor_.async_accept(p->socket(),
[this, p](boost::system::error_code ec)
{
@@ -115,5 +119,8 @@ namespace crow
std::string server_name_ = "Crow/0.1";
uint16_t port_;
unsigned int roundrobin_index_{};
+
+ std::tuple<Middlewares...> middlewares_;
+
};
}
diff --git a/include/middleware.h b/include/middleware.h
index 270e026..5e358af 100644
--- a/include/middleware.h
+++ b/include/middleware.h
@@ -4,6 +4,21 @@
namespace crow
{
+ // Any middleware requires following 3 members:
+
+ // struct context;
+ // storing data for the middleware; can be read from another middleware or handlers
+
+ // template <typename AllContext>
+ // void before_handle(request& req, response& res, context& ctx, AllContext& all_ctx)
+ // called before handling the request.
+ // if res.end() is called, the operation is halted.
+ // (still call after_handle of this middleware)
+
+ // template <typename AllContext>
+ // void after_handle(request& req, response& res, context& ctx, AllContext& all_ctx)
+ // called after handling the request.
+
class CookieParser
{
struct context