-
-
Notifications
You must be signed in to change notification settings - Fork 807
/
main.rs
115 lines (101 loc) · 3.36 KB
/
main.rs
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
use std::io;
use actix_web::{
body::BoxBody,
dev::ServiceResponse,
get,
http::{header::ContentType, StatusCode},
middleware::{ErrorHandlerResponse, ErrorHandlers},
web, App, HttpResponse, HttpServer, Responder, Result,
};
use handlebars::{DirectorySourceOptions, Handlebars};
use serde_json::json;
#[get("/")]
async fn index(hb: web::Data<Handlebars<'_>>) -> impl Responder {
let data = json!({
"name": "Handlebars"
});
let body = hb.render("index", &data).unwrap();
web::Html::new(body)
}
#[get("/{user}/{data}")]
async fn user(hb: web::Data<Handlebars<'_>>, path: web::Path<(String, String)>) -> impl Responder {
let info = path.into_inner();
let data = json!({
"user": info.0,
"data": info.1
});
let body = hb.render("user", &data).unwrap();
web::Html::new(body)
}
#[actix_web::main]
async fn main() -> io::Result<()> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
// Handlebars uses a repository for the compiled templates. This object must be
// shared between the application threads, and is therefore passed to the
// Application Builder as an atomic reference-counted pointer.
let mut handlebars = Handlebars::new();
handlebars
.register_templates_directory(
"./templates",
DirectorySourceOptions {
tpl_extension: ".html".to_owned(),
hidden: false,
temporary: false,
},
)
.unwrap();
let handlebars_ref = web::Data::new(handlebars);
HttpServer::new(move || {
App::new()
.wrap(error_handlers())
.app_data(handlebars_ref.clone())
.service(index)
.service(user)
})
.workers(2)
.bind(("127.0.0.1", 8080))?
.run()
.await
}
// Custom error handlers, to return HTML responses when an error occurs.
fn error_handlers() -> ErrorHandlers<BoxBody> {
ErrorHandlers::new().handler(StatusCode::NOT_FOUND, not_found)
}
// Error handler for a 404 Page not found error.
fn not_found<B>(res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<BoxBody>> {
let response = get_error_response(&res, "Page not found");
Ok(ErrorHandlerResponse::Response(ServiceResponse::new(
res.into_parts().0,
response.map_into_left_body(),
)))
}
// Generic error handler.
fn get_error_response<B>(res: &ServiceResponse<B>, error: &str) -> HttpResponse<BoxBody> {
let request = res.request();
// Provide a fallback to a simple plain text response in case an error occurs during the
// rendering of the error page.
let fallback = |err: &str| {
HttpResponse::build(res.status())
.content_type(ContentType::plaintext())
.body(err.to_string())
};
let hb = request
.app_data::<web::Data<Handlebars>>()
.map(|t| t.get_ref());
match hb {
Some(hb) => {
let data = json!({
"error": error,
"status_code": res.status().as_str()
});
let body = hb.render("error", &data);
match body {
Ok(body) => HttpResponse::build(res.status())
.content_type(ContentType::html())
.body(body),
Err(_) => fallback(error),
}
}
None => fallback(error),
}
}