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
mod app;
mod context;
mod cookie;
mod error;
mod http_method;
mod middleware;
mod middleware_handler;
mod request;
mod response;
#[cfg(feature = "render")]
mod renderer;
pub mod default_middlewares;
pub use app::App;
pub use context::{default_context_generator, Context, DefaultContext};
pub use cookie::{Cookie, CookieOptions, SameSite};
pub use error::Error;
pub use http_method::HttpMethod;
pub use middleware::{DefaultMiddleware, Middleware, NextHandler};
pub use renderer::RenderEngine;
pub use request::Request;
pub use response::Response;
pub use handlebars;
use futures::Future;
use hyper::{
server::conn::AddrStream,
service::{make_service_fn, service_fn},
Body,
Error as HyperError,
Request as HyperRequest,
Response as HyperResponse,
Server,
};
use std::{fmt::Debug, net::SocketAddr, sync::Arc};
pub async fn listen<TContext, TMiddleware, TState, TShutdownSignal>(
app: App<TContext, TMiddleware, TState>,
bind_addr: ([u8; 4], u16),
shutdown_signal: Option<TShutdownSignal>,
) where
TContext: 'static + Context + Debug + Send + Sync,
TMiddleware: 'static + Middleware<TContext> + Clone + Send + Sync,
TState: 'static + Send + Sync,
TShutdownSignal: Future<Output = ()>,
{
let bind_addr = SocketAddr::from(bind_addr);
let app_arc = Arc::new(app);
async move {
let service = make_service_fn(|conn: &AddrStream| {
let app = app_arc.clone();
let remote_addr = conn.remote_addr();
async move {
Ok::<_, HyperError>(service_fn(move |req: HyperRequest<Body>| {
let app = app.clone();
async move {
let request = Request::from_hyper(remote_addr, req).await;
let mut context = app.generate_context(request);
context.header("Server", "Eve");
let result = app.resolve(context).await;
let response = match result {
Ok(context) => context.take_response(),
Err(err) => {
if app.error_handler.is_none() {
return Ok::<_, HyperError>(HyperResponse::new(Body::from(
err.message,
)));
} else {
let response = Response::new();
(app.error_handler.as_ref().unwrap())(response, err.error)
}
}
};
let mut hyper_response = HyperResponse::builder();
for (key, values) in &response.headers {
for value in values {
hyper_response = hyper_response.header(key, value);
}
}
Ok::<HyperResponse<Body>, HyperError>(
hyper_response
.status(response.status)
.body(Body::from(response.body))
.unwrap(),
)
}
}))
}
});
let server = Server::bind(&bind_addr).serve(service);
if let Some(shutdown_signal) = shutdown_signal {
server
.with_graceful_shutdown(shutdown_signal)
.await
.unwrap();
} else {
server.await.unwrap();
}
}
.await
}