forked from rinja-rs/rinja
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
335 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ members = [ | |
"rinja_rocket", | ||
"rinja_warp", | ||
"testing", | ||
"examples/actix-web-app", | ||
] | ||
resolver = "2" | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
[package] | ||
name = "actix-web-app" | ||
version = "0.1.0" | ||
edition = "2021" | ||
publish = false | ||
|
||
[dependencies] | ||
rinja_actix = { version = "0.15.0", path = "../../rinja_actix" } | ||
|
||
actix-web = { version = "4.8.0", default-features = false, features = ["macros"] } | ||
env_logger = "0.11.3" | ||
log = "0.4.22" | ||
pretty-error-debug = "0.3.0" | ||
serde = { version = "1.0.203", features = ["derive"] } | ||
strum = { version = "0.26.3", features = ["derive"] } | ||
thiserror = "1.0.61" | ||
tokio = { version = "1.38.0", features = ["sync", "rt-multi-thread"] } | ||
|
||
[workspace] | ||
members = ["."] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../LICENSE-APACHE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../LICENSE-MIT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
use actix_web::http::{header, Method}; | ||
use actix_web::{ | ||
get, middleware, web, App, Either, HttpRequest, HttpResponse, HttpServer, Responder, Result, | ||
}; | ||
use rinja_actix::Template; | ||
use serde::Deserialize; | ||
use tokio::runtime; | ||
|
||
fn main() -> Result<(), Error> { | ||
let env = env_logger::Env::new().default_filter_or("info"); | ||
env_logger::try_init_from_env(env).map_err(Error::Log)?; | ||
|
||
runtime::Builder::new_multi_thread() | ||
.enable_all() | ||
.build() | ||
.map_err(Error::Rt)? | ||
.block_on(amain()) | ||
} | ||
|
||
async fn amain() -> Result<(), Error> { | ||
let server = HttpServer::new(|| { | ||
App::new() | ||
.wrap(middleware::Logger::default()) | ||
.wrap(middleware::NormalizePath::new( | ||
middleware::TrailingSlash::MergeOnly, | ||
)) | ||
.service(start_handler) | ||
.service(index_handler) | ||
.service(greeting_handler) | ||
.default_service(web::to(not_found_handler)) | ||
}); | ||
let server = server.bind(("127.0.0.1", 8080)).map_err(Error::Bind)?; | ||
for addr in server.addrs() { | ||
println!("Listening on: http://{addr}/"); | ||
} | ||
server.run().await.map_err(Error::Run) | ||
} | ||
|
||
#[derive(thiserror::Error, pretty_error_debug::Debug)] | ||
enum Error { | ||
#[error("could not setup logger")] | ||
Log(#[source] log::SetLoggerError), | ||
#[error("could not setup async runtime")] | ||
Rt(#[source] std::io::Error), | ||
#[error("could not bind socket")] | ||
Bind(#[source] std::io::Error), | ||
#[error("could not run server")] | ||
Run(#[source] std::io::Error), | ||
} | ||
|
||
#[derive(Default, Debug, Clone, Copy, PartialEq, Deserialize, strum::Display, strum::AsRefStr)] | ||
#[allow(non_camel_case_types)] | ||
enum Lang { | ||
#[default] | ||
en, | ||
de, | ||
} | ||
|
||
async fn not_found_handler(req: HttpRequest) -> Result<impl Responder> { | ||
#[derive(Debug, Template)] | ||
#[template(path = "404.html")] | ||
struct Tmpl { | ||
req: HttpRequest, | ||
lang: Lang, | ||
} | ||
|
||
match req.method() { | ||
&Method::GET => Ok(Either::Left(Tmpl { | ||
req, | ||
lang: Lang::default(), | ||
})), | ||
_ => Ok(Either::Right(HttpResponse::MethodNotAllowed().finish())), | ||
} | ||
} | ||
|
||
#[get("/")] | ||
async fn start_handler(req: HttpRequest) -> Result<impl Responder> { | ||
let url = req.url_for("index_handler", [Lang::default()])?; | ||
Ok(HttpResponse::Found() | ||
.insert_header((header::LOCATION, url.as_str())) | ||
.finish()) | ||
} | ||
|
||
#[derive(Debug, Deserialize)] | ||
struct IndexHandlerQuery { | ||
#[serde(default)] | ||
name: String, | ||
} | ||
|
||
#[get("/{lang}/index.html")] | ||
async fn index_handler( | ||
req: HttpRequest, | ||
path: web::Path<(Lang,)>, | ||
web::Query(query): web::Query<IndexHandlerQuery>, | ||
) -> Result<impl Responder> { | ||
#[derive(Debug, Template)] | ||
#[template(path = "index.html")] | ||
struct Tmpl { | ||
req: HttpRequest, | ||
lang: Lang, | ||
name: String, | ||
} | ||
|
||
let (lang,) = path.into_inner(); | ||
Ok(Tmpl { | ||
req, | ||
lang, | ||
name: query.name, | ||
}) | ||
} | ||
|
||
#[derive(Debug, Deserialize)] | ||
struct GreetingHandlerQuery { | ||
name: String, | ||
} | ||
|
||
#[get("/{lang}/greet-me.html")] | ||
async fn greeting_handler( | ||
req: HttpRequest, | ||
path: web::Path<(Lang,)>, | ||
web::Query(query): web::Query<GreetingHandlerQuery>, | ||
) -> Result<impl Responder> { | ||
#[derive(Debug, Template)] | ||
#[template(path = "greet.html")] | ||
struct Tmpl { | ||
req: HttpRequest, | ||
lang: Lang, | ||
name: String, | ||
} | ||
|
||
let (lang,) = path.into_inner(); | ||
Ok(Tmpl { | ||
req, | ||
lang, | ||
name: query.name, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{% extends "_layout.html" %} | ||
|
||
{% block title -%} | ||
404: Not Found | ||
{%- endblock %} | ||
|
||
{% block content -%} | ||
<h1>404: Not Found</h1> | ||
<h2><a href="{{ req.url_for_static("start_handler")? }}">Back to the first page.</a></h2> | ||
{%- endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<!DOCTYPE html> | ||
<html lang="{{lang}}"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<title>{% block title %}{% endblock %}</title> | ||
<meta http-equiv="expires" content="Sat, 01 Dec 2001 00:00:00 GMT" /> | ||
<meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate" /> | ||
<meta http-equiv="pragma" content="no-cache" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
<meta name="robots" content="noindex, nofollow" /> | ||
|
||
<style> | ||
/*<![CDATA[*/ | ||
html { | ||
background-color: #eee; | ||
color: #111; | ||
font-size: 62.5%; | ||
min-height: 100vh; | ||
color-scheme: light; | ||
} | ||
* { | ||
line-height: 1.2em; | ||
} | ||
body { | ||
background-color: #fff; | ||
font-size: 1.8rem; | ||
max-width: 40em; | ||
margin: 1em auto; | ||
padding: 2em; | ||
} | ||
h1 { font-size: 2.4rem; } | ||
h2 { font-size: 2.2rem; } | ||
h3 { font-size: 2.0rem; } | ||
a:link, a:visited { | ||
color: #36c; | ||
text-decoration: none; | ||
} | ||
a:active, a:hover, a:focus { | ||
text-decoration: underline; | ||
text-underline-offset: 0.3em; | ||
} | ||
#lang-select { | ||
font-size: 80%; | ||
width: max-content; | ||
margin: 2em 0 0 auto; | ||
} | ||
/*]]>*/ | ||
</style> | ||
</head> | ||
<body> | ||
{%~ block content %}{% endblock ~%} | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
{% extends "_layout.html" %} | ||
|
||
{% block title -%} | ||
{%- match lang -%} | ||
{%- when Lang::en -%} Hello, {{name}}! | ||
{%- when Lang::de -%} Hallo, {{name}}! | ||
{%- endmatch -%} | ||
{%- endblock %} | ||
|
||
{%- block content -%} | ||
<h1> | ||
{%- match lang -%} | ||
{%- when Lang::en -%} Hello | ||
{%- when Lang::de -%} Hallo | ||
{%- endmatch -%} | ||
</h1> | ||
<p> | ||
{%- match lang -%} | ||
{%- when Lang::en -%} | ||
Hello, <strong>{{name}}</strong>, nice to meet you! {#-~#} | ||
I'm a <a href="https://rinja.readthedocs.io/en/latest/">Rinja</a> example application. | ||
{%- when Lang::de -%} | ||
Hallo, <strong>{{name}}</strong>, schön dich kennenzulernen! {#-~#} | ||
Ich bin eine <a href="https://rinja.readthedocs.io/en/latest/">Rinja</a>-Beispielanwendung. | ||
{%- endmatch -%} | ||
</p> | ||
<h2> | ||
<a href="{{ req.url_for("index_handler", [lang])? }}?name={{ name|urlencode }}"> | ||
{%- match lang -%} | ||
{%- when Lang::en -%} Back to the first page. | ||
{%- when Lang::de -%} Zurück zur ersten Seite. | ||
{%- endmatch -%} | ||
</a> | ||
</h2> | ||
|
||
<ul id="lang-select"> | ||
{%- if lang != Lang::en -%} | ||
<li><a href="{{ req.url_for("greeting_handler", [Lang::en])? }}?name={{ name|urlencode }}">This page in English</a></li> | ||
{%- endif -%} | ||
{%- if lang != Lang::de -%} | ||
<li><a href="{{ req.url_for("greeting_handler", [Lang::de])? }}?name={{ name|urlencode }}">Diese Seite auf deutsch.</a></li> | ||
{%- endif -%} | ||
</ul> | ||
{%- endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
{% extends "_layout.html" %} | ||
|
||
{% block title -%} | ||
{%- match lang -%} | ||
{%- when Lang::en -%} Hello | ||
{%- when Lang::de -%} Hallo | ||
{%- endmatch -%} | ||
{%- endblock %} | ||
|
||
{%- block content -%} | ||
<h1> | ||
{%- match lang -%} | ||
{%- when Lang::en -%} Hello | ||
{%- when Lang::de -%} Hallo | ||
{%- endmatch -%} | ||
</h1> | ||
<form | ||
method="GET" | ||
action="{{ req.url_for("greeting_handler", [lang])? }}" | ||
autocomplete="off" | ||
> | ||
<p> | ||
{%- match lang -%} | ||
{%- when Lang::en -%} | ||
I would like to say <em>hello</em>. {#-~#} | ||
Would you please tell me your name? | ||
{%- when Lang::de -%} | ||
Ich möchte dir gerne <em>hallo</em> sagen. {#-~#} | ||
Bitte nenne mir doch deinen Namen! | ||
{%- endmatch -%} | ||
</p> | ||
<p> | ||
<label> | ||
{%- match lang -%} | ||
{%- when Lang::en -%} My name is | ||
{%- when Lang::de -%} Ich heiße | ||
{%- endmatch -%}: | ||
<input | ||
type="text" | ||
value="{{name}}" | ||
name="name" | ||
required | ||
style="width: 10em" | ||
/> | ||
</label> | ||
</p> | ||
<p> | ||
<label> | ||
<button type="submit"> | ||
{%- match lang -%} | ||
{%- when Lang::en -%} Greet me, then! | ||
{%- when Lang::de -%} Dann begrüße mich! | ||
{%- endmatch -%} | ||
</button> | ||
</label> | ||
</p> | ||
</form> | ||
|
||
<ul id="lang-select"> | ||
{%- if lang != Lang::en -%} | ||
<li><a href="{{ req.url_for("index_handler", [Lang::en])? }}">This page in English</a></li> | ||
{%- endif -%} | ||
{%- if lang != Lang::de -%} | ||
<li><a href="{{ req.url_for("index_handler", [Lang::de])? }}">Diese Seite auf deutsch.</a></li> | ||
{%- endif -%} | ||
</ul> | ||
{%- endblock %} |