diff --git a/.gitignore b/.gitignore index 72bdb47..b153e47 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,7 @@ Cargo.lock **/*.rs.bk # intellij files -.idea/** +**/.idea/** .history/ diff --git a/Cargo.toml b/Cargo.toml index 0be6323..1981d62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,6 +41,7 @@ members = [ "template_askama", "template_handlebars", "template_tera", + "template_tinytemplate", "template_yarte", "todo", "udp-echo", diff --git a/simple-auth-server/src/auth_handler.rs b/simple-auth-server/src/auth_handler.rs index ccb8780..f08f1fa 100644 --- a/simple-auth-server/src/auth_handler.rs +++ b/simple-auth-server/src/auth_handler.rs @@ -5,7 +5,7 @@ use actix_web::{ }; use diesel::prelude::*; use diesel::PgConnection; -use futures::future::{Ready, ok, err}; +use futures::future::{err, ok, Ready}; use serde::Deserialize; use crate::errors::ServiceError; diff --git a/template_tinytemplate/Cargo.toml b/template_tinytemplate/Cargo.toml new file mode 100644 index 0000000..a079b99 --- /dev/null +++ b/template_tinytemplate/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "template-tinytemplate" +version = "2.0.0" +authors = ["Hanif Bin Ariffin "] +edition = "2018" + +[dependencies] +env_logger = "0.7" +tinytemplate = "1.1" +serde = "1" +serde_derive = "1" +actix-http = "1" +actix-web = "2" +actix-rt = "1" +serde_json = "1" diff --git a/template_tinytemplate/README.md b/template_tinytemplate/README.md new file mode 100644 index 0000000..d86b3a7 --- /dev/null +++ b/template_tinytemplate/README.md @@ -0,0 +1,18 @@ +# template_tinytemplate + +See the documentation for the minimalist template engine [tiny_template](https://docs.rs/tinytemplate/1.1.0/tinytemplate/). + +## Usage + +### Server + +```bash +cd examples/template_tinytemplate +cargo run # (or ``cargo watch -x run``) +# Started http server: 127.0.0.1:8080 +``` + +### Web Client + +- [http://localhost:8080](http://localhost:8080) +- [http://localhost:8080/non-existing-page](http://localhost:8080/non-existing-page) - 404 page rendered using template diff --git a/template_tinytemplate/src/main.rs b/template_tinytemplate/src/main.rs new file mode 100644 index 0000000..5993313 --- /dev/null +++ b/template_tinytemplate/src/main.rs @@ -0,0 +1,101 @@ +use std::collections::HashMap; + +use actix_http::{body::Body, Response}; +use actix_web::dev::ServiceResponse; +use actix_web::http::StatusCode; +use actix_web::middleware::errhandlers::{ErrorHandlerResponse, ErrorHandlers}; +use actix_web::{error, middleware, web, App, Error, HttpResponse, HttpServer, Result}; +use serde_json::json; +use tinytemplate::TinyTemplate; + +// store tiny_template in application state +async fn index( + tmpl: web::Data>, + query: web::Query>, +) -> Result { + let s = if let Some(name) = query.get("name") { + // submitted form + let ctx = json!({ + "name" : name.to_owned(), + "text" : "Welcome!".to_owned() + }); + tmpl.render("user.html", &ctx) + .map_err(|_| error::ErrorInternalServerError("Template error"))? + } else { + tmpl.render("index.html", &serde_json::Value::Null) + .map_err(|_| error::ErrorInternalServerError("Template error"))? + }; + Ok(HttpResponse::Ok().content_type("text/html").body(s)) +} + +#[actix_rt::main] +async fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); + env_logger::init(); + + HttpServer::new(|| { + let mut tt = TinyTemplate::new(); + tt.add_template("index.html", INDEX).unwrap(); + tt.add_template("user.html", USER).unwrap(); + tt.add_template("error.html", ERROR).unwrap(); + + App::new() + .data(tt) + .wrap(middleware::Logger::default()) // enable logger + .service(web::resource("/").route(web::get().to(index))) + .service(web::scope("").wrap(error_handlers())) + }) + .bind("127.0.0.1:8080")? + .run() + .await +} + +// Custom error handlers, to return HTML responses when an error occurs. +fn error_handlers() -> ErrorHandlers { + ErrorHandlers::new().handler(StatusCode::NOT_FOUND, not_found) +} + +// Error handler for a 404 Page not found error. +fn not_found(res: ServiceResponse) -> Result> { + let response = get_error_response(&res, "Page not found"); + Ok(ErrorHandlerResponse::Response( + res.into_response(response.into_body()), + )) +} + +// Generic error handler. +fn get_error_response(res: &ServiceResponse, error: &str) -> Response { + 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 = |e: &str| { + Response::build(res.status()) + .content_type("text/plain") + .body(e.to_string()) + }; + + let tt = request + .app_data::>>() + .map(|t| t.get_ref()); + match tt { + Some(tt) => { + let mut context = std::collections::HashMap::new(); + context.insert("error", error.to_owned()); + context.insert("status_code", res.status().as_str().to_owned()); + let body = tt.render("error.html", &context); + + match body { + Ok(body) => Response::build(res.status()) + .content_type("text/html") + .body(body), + Err(_) => fallback(error), + } + } + None => fallback(error), + } +} + +static ERROR: &str = include_str!("../templates/error.html"); +static INDEX: &str = include_str!("../templates/index.html"); +static USER: &str = include_str!("../templates/user.html"); diff --git a/template_tinytemplate/templates/error.html b/template_tinytemplate/templates/error.html new file mode 100644 index 0000000..7af82bd --- /dev/null +++ b/template_tinytemplate/templates/error.html @@ -0,0 +1,10 @@ + + + + + {error} + + +

{status_code} {error}

+ + diff --git a/template_tinytemplate/templates/index.html b/template_tinytemplate/templates/index.html new file mode 100644 index 0000000..d8a47bc --- /dev/null +++ b/template_tinytemplate/templates/index.html @@ -0,0 +1,17 @@ + + + + + Actix web + + +

Welcome!

+

+

What is your name?

+
+
+

+
+

+ + diff --git a/template_tinytemplate/templates/user.html b/template_tinytemplate/templates/user.html new file mode 100644 index 0000000..9f1a7b5 --- /dev/null +++ b/template_tinytemplate/templates/user.html @@ -0,0 +1,11 @@ + + + + + Actix web + + +

Hi, {name}!

+

{text}

+ + diff --git a/udp-echo/src/main.rs b/udp-echo/src/main.rs index 819992d..279a789 100644 --- a/udp-echo/src/main.rs +++ b/udp-echo/src/main.rs @@ -43,14 +43,14 @@ async fn main() { ); let (sink, stream) = UdpFramed::new(sock, BytesCodec::new()).split(); UdpActor::create(|ctx| { - ctx.add_stream( - stream.filter_map( - |item: Result<(BytesMut, SocketAddr)>| async { - item.map(|(data, sender)| UdpPacket(data, sender)).ok() - }, - ), - ); - UdpActor { sink: SinkWrite::new(sink, ctx), } + ctx.add_stream(stream.filter_map( + |item: Result<(BytesMut, SocketAddr)>| async { + item.map(|(data, sender)| UdpPacket(data, sender)).ok() + }, + )); + UdpActor { + sink: SinkWrite::new(sink, ctx), + } }); actix_rt::Arbiter::local_join().await;