summaryrefslogtreecommitdiff
path: root/http/middleware_context.h
blob: fbe1d80e968f2f3b6102f4c757d3757903ccda9c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#pragma once

#include "http_request.h"
#include "http_response.h"
#include "utility.h"

namespace crow
{
namespace detail
{
template <typename... Middlewares>
struct PartialContext
    : public black_magic::PopBack<Middlewares...>::template rebind<
          PartialContext>,
      public black_magic::LastElementType<Middlewares...>::type::Context
{
    using parent_context = typename black_magic::PopBack<
        Middlewares...>::template rebind<::crow::detail::PartialContext>;
    template <size_t N>
    using partial = typename std::conditional<
        N == sizeof...(Middlewares) - 1, PartialContext,
        typename parent_context::template partial<N>>::type;

    template <typename T> typename T::Context& get()
    {
        return static_cast<typename T::Context&>(*this);
    }
};

template <> struct PartialContext<>
{
    template <size_t> using partial = PartialContext;
};

template <size_t N, typename Context, typename Container, typename CurrentMW,
          typename... Middlewares>
bool middlewareCallHelper(Container& middlewares, Request& req, Response& res,
                          Context& ctx);

template <typename... Middlewares>
struct Context : private PartialContext<Middlewares...>
// struct Context : private Middlewares::context... // simple but less type-safe
{
    template <size_t N, typename Context, typename Container>
    friend typename std::enable_if<(N == 0)>::type
        afterHandlersCallHelper(Container& middlewares, Context& ctx,
                                Request& req, Response& res);
    template <size_t N, typename Context, typename Container>
    friend typename std::enable_if<(N > 0)>::type
        afterHandlersCallHelper(Container& middlewares, Context& ctx,
                                Request& req, Response& res);

    template <size_t N, typename Context, typename Container,
              typename CurrentMW, typename... Middlewares2>
    friend bool middlewareCallHelper(Container& middlewares, Request& req,
                                     Response& res, Context& ctx);

    template <typename T> typename T::Context& get()
    {
        return static_cast<typename T::Context&>(*this);
    }

    template <size_t N>
    using partial =
        typename PartialContext<Middlewares...>::template partial<N>;
};
} // namespace detail
} // namespace crow