diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/crow.h | 19 | ||||
-rw-r--r-- | include/http_request.h | 2 | ||||
-rw-r--r-- | include/middleware.h | 50 | ||||
-rw-r--r-- | include/middleware_context.h | 32 | ||||
-rw-r--r-- | include/utility.h | 73 |
5 files changed, 175 insertions, 1 deletions
diff --git a/include/crow.h b/include/crow.h index 55572bf..a018f31 100644 --- a/include/crow.h +++ b/include/crow.h @@ -13,6 +13,8 @@ #include "http_server.h" #include "utility.h" #include "routing.h" +#include "middleware_impl.h" +#include "http_request.h" // TEST #include <iostream> @@ -21,6 +23,7 @@ namespace crow { + template <typename ... Middlewares> class Crow { public: @@ -78,12 +81,26 @@ namespace crow router_.debug_print(); } + // middleware + using context_t = detail::context<Middlewares...>; + template <typename T> + T& get_middleware_context(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>(); + } + private: uint16_t port_ = 80; uint16_t concurrency_ = 1; + std::tuple<Middlewares...> middlewares_; + Router router_; }; - using App = Crow; + template <typename ... Middlewares> + using App = Crow<Middlewares...>; + using SimpleApp = Crow<>; }; diff --git a/include/http_request.h b/include/http_request.h index 83b6059..77b3ecb 100644 --- a/include/http_request.h +++ b/include/http_request.h @@ -10,5 +10,7 @@ namespace crow std::string url; std::unordered_map<std::string, std::string> headers; std::string body; + + void* middleware_context; }; } diff --git a/include/middleware.h b/include/middleware.h new file mode 100644 index 0000000..270e026 --- /dev/null +++ b/include/middleware.h @@ -0,0 +1,50 @@ +#pragma once +#include "http_request.h" +#include "http_response.h" + +namespace crow +{ + class CookieParser + { + struct context + { + std::unordered_map<std::string, std::string> jar; + }; + + template <typename AllContext> + void before_handle(request& req, response& res, context& ctx, AllContext& all_ctx) + { + // ctx == all_ctx.bind<CookieParser>() + // ctx.jar[] = ; + } + + template <typename AllContext> + void after_handle(request& req, response& res, context& ctx, AllContext& all_ctx) + { + } + } + + /* + App<CookieParser, AnotherJarMW> app; + A B C + A::context + int aa; + + ctx1 : public A::context + ctx2 : public ctx1, public B::context + ctx3 : public ctx2, public C::context + + C depends on A + + C::handle + context.aaa + + App::context : private CookieParser::contetx, ... + { + jar + + } + + SimpleApp + */ +} diff --git a/include/middleware_context.h b/include/middleware_context.h new file mode 100644 index 0000000..6dbf923 --- /dev/null +++ b/include/middleware_context.h @@ -0,0 +1,32 @@ +#pragma once + +#include "utility.h" + +namespace crow +{ + namespace detail + { + template <typename ... Middlewares> + struct partial_context + : public black_magic::pop_back<Middlewares...>::template rebind<partial_context> + , public black_magic::last_element_type<Middlewares...>::type::context + { + }; + + template <> + struct partial_context<> + { + }; + + template <typename ... Middlewares> + struct context : private partial_context<Middlewares...> + //struct context : private Middlewares::context... // simple but less type-safe + { + template <typename T> + typename T::context& get() + { + return static_cast<typename T::context&>(*this); + } + }; + } +} diff --git a/include/utility.h b/include/utility.h index a46d577..35ea848 100644 --- a/include/utility.h +++ b/include/utility.h @@ -2,6 +2,8 @@ #include <cstdint> #include <stdexcept> +#include <tuple> +#include <type_traits> namespace crow { @@ -211,5 +213,76 @@ template <typename F, typename Set> using type = S<>; }; + template <typename ... T> + struct last_element_type + { + using type = typename std::tuple_element<sizeof...(T)-1, std::tuple<T...>>::type; + }; + + + template <> + struct last_element_type<> + { + }; + + + // from http://stackoverflow.com/questions/13072359/c11-compile-time-array-with-logarithmic-evaluation-depth + template<class T> using Invoke = typename T::type; + + template<unsigned...> struct seq{ using type = seq; }; + + template<class S1, class S2> struct concat; + + template<unsigned... I1, unsigned... I2> + struct concat<seq<I1...>, seq<I2...>> + : seq<I1..., (sizeof...(I1)+I2)...>{}; + + template<class S1, class S2> + using Concat = Invoke<concat<S1, S2>>; + + template<unsigned N> struct gen_seq; + template<unsigned N> using GenSeq = Invoke<gen_seq<N>>; + + template<unsigned N> + struct gen_seq : Concat<GenSeq<N/2>, GenSeq<N - N/2>>{}; + + template<> struct gen_seq<0> : seq<>{}; + template<> struct gen_seq<1> : seq<0>{}; + + template <typename Seq, typename Tuple> + struct pop_back_helper; + + template <unsigned ... N, typename Tuple> + struct pop_back_helper<seq<N...>, Tuple> + { + template <template <typename ... Args> class U> + using rebind = U<std::tuple_element<N, Tuple>...>; + }; + + template <typename ... T> + struct pop_back : public pop_back_helper<typename gen_seq<sizeof...(T)-1>::type, std::tuple<T...>> + { + }; + + template <> + struct pop_back<> + { + template <template <typename ... Args> class U> + using rebind = U<>; + }; + + // from http://stackoverflow.com/questions/2118541/check-if-c0x-parameter-pack-contains-a-type + template < typename Tp, typename... List > + struct contains : std::true_type {}; + + template < typename Tp, typename Head, typename... Rest > + struct contains<Tp, Head, Rest...> + : std::conditional< std::is_same<Tp, Head>::value, + std::true_type, + contains<Tp, Rest...> + >::type {}; + + template < typename Tp > + struct contains<Tp> : std::false_type {}; } } |