2022-07-09 21:08:11 +01:00
|
|
|
use std::io;
|
|
|
|
|
|
|
|
use actix_web::{
|
|
|
|
body::BoxBody,
|
|
|
|
dev::ServiceResponse,
|
|
|
|
get,
|
|
|
|
http::{header::ContentType, StatusCode},
|
|
|
|
middleware::{ErrorHandlerResponse, ErrorHandlers},
|
2024-03-05 22:30:51 +00:00
|
|
|
web, App, HttpResponse, HttpServer, Responder, Result,
|
2022-07-09 21:08:11 +01:00
|
|
|
};
|
2024-03-04 13:05:13 +01:00
|
|
|
use handlebars::{DirectorySourceOptions, Handlebars};
|
2022-02-02 15:17:17 +00:00
|
|
|
use serde_json::json;
|
2019-06-08 18:47:39 +01:00
|
|
|
|
|
|
|
#[get("/")]
|
2024-03-05 22:30:51 +00:00
|
|
|
async fn index(hb: web::Data<Handlebars<'_>>) -> impl Responder {
|
2019-06-08 18:47:39 +01:00
|
|
|
let data = json!({
|
|
|
|
"name": "Handlebars"
|
|
|
|
});
|
|
|
|
let body = hb.render("index", &data).unwrap();
|
|
|
|
|
2024-07-07 00:23:03 +01:00
|
|
|
web::Html::new(body)
|
2019-06-08 18:47:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[get("/{user}/{data}")]
|
2024-03-05 22:30:51 +00:00
|
|
|
async fn user(hb: web::Data<Handlebars<'_>>, path: web::Path<(String, String)>) -> impl Responder {
|
2022-02-02 15:17:17 +00:00
|
|
|
let info = path.into_inner();
|
2019-06-08 18:47:39 +01:00
|
|
|
let data = json!({
|
|
|
|
"user": info.0,
|
|
|
|
"data": info.1
|
|
|
|
});
|
|
|
|
let body = hb.render("user", &data).unwrap();
|
|
|
|
|
2024-07-07 00:23:03 +01:00
|
|
|
web::Html::new(body)
|
2019-06-08 18:47:39 +01:00
|
|
|
}
|
|
|
|
|
2020-09-12 16:49:45 +01:00
|
|
|
#[actix_web::main]
|
2019-12-07 23:59:24 +06:00
|
|
|
async fn main() -> io::Result<()> {
|
2024-03-05 22:30:51 +00:00
|
|
|
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
|
|
|
|
2019-06-08 18:47:39 +01:00
|
|
|
// 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
|
2024-03-04 13:05:13 +01:00
|
|
|
.register_templates_directory(
|
2024-03-05 22:30:51 +00:00
|
|
|
"./templates",
|
2024-03-04 13:05:13 +01:00
|
|
|
DirectorySourceOptions {
|
|
|
|
tpl_extension: ".html".to_owned(),
|
|
|
|
hidden: false,
|
|
|
|
temporary: false,
|
|
|
|
},
|
|
|
|
)
|
2019-06-08 18:47:39 +01:00
|
|
|
.unwrap();
|
2019-06-22 09:07:39 +02:00
|
|
|
let handlebars_ref = web::Data::new(handlebars);
|
2019-06-08 18:47:39 +01:00
|
|
|
|
|
|
|
HttpServer::new(move || {
|
|
|
|
App::new()
|
2020-05-19 18:21:39 +03:00
|
|
|
.wrap(error_handlers())
|
2019-12-20 22:30:26 +06:00
|
|
|
.app_data(handlebars_ref.clone())
|
2019-06-08 18:47:39 +01:00
|
|
|
.service(index)
|
|
|
|
.service(user)
|
|
|
|
})
|
2024-03-05 22:30:51 +00:00
|
|
|
.workers(2)
|
2022-02-17 20:22:36 +00:00
|
|
|
.bind(("127.0.0.1", 8080))?
|
2019-12-25 20:48:33 +04:00
|
|
|
.run()
|
2019-12-07 23:59:24 +06:00
|
|
|
.await
|
2019-06-08 18:47:39 +01:00
|
|
|
}
|
2020-05-19 18:21:39 +03:00
|
|
|
|
|
|
|
// Custom error handlers, to return HTML responses when an error occurs.
|
2022-02-02 15:17:17 +00:00
|
|
|
fn error_handlers() -> ErrorHandlers<BoxBody> {
|
2020-05-19 18:21:39 +03:00
|
|
|
ErrorHandlers::new().handler(StatusCode::NOT_FOUND, not_found)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Error handler for a 404 Page not found error.
|
2022-02-02 15:17:17 +00:00
|
|
|
fn not_found<B>(res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<BoxBody>> {
|
2020-05-19 18:21:39 +03:00
|
|
|
let response = get_error_response(&res, "Page not found");
|
2022-02-02 15:17:17 +00:00
|
|
|
Ok(ErrorHandlerResponse::Response(ServiceResponse::new(
|
|
|
|
res.into_parts().0,
|
|
|
|
response.map_into_left_body(),
|
|
|
|
)))
|
2020-05-19 18:21:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Generic error handler.
|
2022-02-18 02:44:02 +00:00
|
|
|
fn get_error_response<B>(res: &ServiceResponse<B>, error: &str) -> HttpResponse<BoxBody> {
|
2020-05-19 18:21:39 +03:00
|
|
|
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.
|
2023-07-09 03:32:47 +01:00
|
|
|
let fallback = |err: &str| {
|
2022-02-02 15:17:17 +00:00
|
|
|
HttpResponse::build(res.status())
|
|
|
|
.content_type(ContentType::plaintext())
|
2023-07-09 03:32:47 +01:00
|
|
|
.body(err.to_string())
|
2020-05-19 18:21:39 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
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 {
|
2022-02-02 15:17:17 +00:00
|
|
|
Ok(body) => HttpResponse::build(res.status())
|
|
|
|
.content_type(ContentType::html())
|
2020-05-19 18:21:39 +03:00
|
|
|
.body(body),
|
2022-02-02 15:21:49 +00:00
|
|
|
Err(_) => fallback(error),
|
2020-05-19 18:21:39 +03:00
|
|
|
}
|
|
|
|
}
|
2022-02-02 15:21:49 +00:00
|
|
|
None => fallback(error),
|
2020-05-19 18:21:39 +03:00
|
|
|
}
|
|
|
|
}
|