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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
use lunatic::function::reference::Fn as FnPtr;
use lunatic::function::FuncRef;
use serde::de::DeserializeOwned;
use serde::Serialize;

use crate::extract::{FromOwnedRequest, FromRequest};
use crate::response::IntoResponse;
use crate::{RequestContext, Response};

/// Implemented for process-safe [`Handlers`](Handler).
///
/// Submillisecond handles every request in a separate lunatic process, and
/// lunatic's processes are sandboxed. This means that no memory is shared
/// between the request handler and the rest of the app. This introduces an
/// additional limitation on what can be a [`Handler`].
///
/// Two kinds of types are safe to be used as handlers:
/// - Static functions
/// - Serializable and clonable objects
///
/// ### Static functions
///
/// This type is obvious. Non-capturing functions are generated during compile
/// time and are shared between all processes, so they can be easily used as
/// handlers. In fact, the [`router!`](crate::router) macro will in the end just
/// generate a function that will be used as a handler and invoke other handlers
/// depending on the request values.
///
/// ### Serializable and clonable objects
///
/// Everything else needs to be passed somehow to the memory of the handler
/// process. This means that we need to clone the value for every incoming
/// request, serialize it and send it to the process handling the request.
pub trait ProcessSafeHandler<Kind, Arg, Ret> {
    /// A handler is only safe if it can be cloned and safely sent between
    /// processes.
    type SafeHandler: Handler<Arg, Ret> + Clone + Serialize + DeserializeOwned;

    /// Turn type into a safe handler.
    fn safe_handler(self) -> Self::SafeHandler;
}

/// Marker type for functions that satisfy [`ProcessSafeHandler`].
pub struct Function;
/// Marker type for objects that satisfy [`ProcessSafeHandler`].
pub struct Object;

impl<T, Arg, Ret> ProcessSafeHandler<Function, Arg, Ret> for T
where
    T: FnPtr<T> + Copy,
    FuncRef<T>: Handler<Arg, Ret>,
{
    type SafeHandler = FuncRef<T>;

    fn safe_handler(self) -> Self::SafeHandler {
        FuncRef::new(self)
    }
}

impl<T, Arg, Ret> ProcessSafeHandler<Object, Arg, Ret> for T
where
    T: Clone + Handler<Arg, Ret> + Serialize + DeserializeOwned,
{
    type SafeHandler = T;

    fn safe_handler(self) -> Self::SafeHandler {
        self
    }
}

impl<T, Arg, Ret> Handler<Arg, Ret> for FuncRef<T>
where
    T: FnPtr<T> + Copy + Handler<Arg, Ret>,
{
    fn handle(&self, req: RequestContext) -> Response {
        self.get().handle(req)
    }
}

/// A handler is implemented for any function which takes any number of
/// [extractors](crate::extract), and returns any type that implements
/// [`IntoResponse`].
///
/// To avoid unnecessary clones, the [`RequestContext`], [`http::Request`],
/// [`String`], [`Vec<u8>`], [`Params`](crate::params::Params) extractors (and
/// any other types which implement [`FromOwnedRequest`] directly) should be
/// placed as the first argument, and cannot be used together in a single
/// handler.
///
/// A maximum of 16 extractor arguments may be added for a single handler.
///
/// # Handler examples
///
/// ```
/// fn index() -> &'static str {
///     "Hello, submillisecond"
/// }
///
/// use submillisecond::extract::Path;
/// use submillisecond::http::status::FOUND;
///
/// fn headers(Path(id): Path<String>) -> (StatusCode, String) {
///     (FOUND, id)
/// }
/// ```
///
/// # Middleware example
///
/// ```
/// use submillisecond::RequestContent;
/// use submillisecond::response::Response;
///
/// fn logging_layer(req: RequestContext) -> Response {
///     println!("Incoming request start");
///     let res = req.next_handler();
///     println!("Incoming request end");
///     res
/// }
/// ```
pub trait Handler<Arg = (), Ret = ()> {
    /// Handles the request, returning a response.
    fn handle(&self, req: RequestContext) -> Response;

    /// Initializes handler, useful for spawning processes on startup.
    fn init(&self) {}
}

impl<F, R> Handler<(), R> for F
where
    F: Fn() -> R,
    R: IntoResponse,
{
    fn handle(&self, _req: RequestContext) -> Response {
        self().into_response()
    }
}

macro_rules! impl_handler {
    ( $arg1: ident $(, $( $args: ident ),*)? ) => {
        #[allow(unused_parens)]
        impl<F, $arg1, $( $( $args, )*)? R> Handler<($arg1$(, $( $args, )*)?), R> for F
        where
            F: Fn($arg1$(, $( $args, )*)?) -> R,
            $arg1: FromOwnedRequest,
            $( $( $args: FromRequest, )* )?
            R: IntoResponse,
        {

            #[allow(unused_mut, unused_variables)]
            fn handle(&self, mut req: RequestContext) -> Response {
                paste::paste! {
                    $($(
                        let [< $args:lower >] = match <$args as FromRequest>::from_request(&mut req) {
                            Ok(e) => e,
                            Err(err) => return err.into_response(),
                        };
                    )*)?
                    let e1 = match <$arg1 as FromOwnedRequest>::from_owned_request(req) {
                        Ok(e) => e,
                        Err(err) => return err.into_response(),
                    };
                    self(e1 $(, $( [< $args:lower >] ),*)?).into_response()
                }
            }
        }
    };
}

all_the_tuples!(impl_handler);