aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/csrf/Cargo.toml14
-rw-r--r--examples/csrf/src/main.rs59
2 files changed, 73 insertions, 0 deletions
diff --git a/examples/csrf/Cargo.toml b/examples/csrf/Cargo.toml
new file mode 100644
index 0000000..1f0066b
--- /dev/null
+++ b/examples/csrf/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "csrf"
+version = "0.1.0"
+authors = ["Martin Fischer <martin@push-f.com>"]
+edition = "2018"
+publish = false
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+hyper = "0.13"
+sputnik = {path = "../../"}
+serde = { version = "1.0", features = ["derive"] }
+tokio = { version = "0.2", features = ["full"] } \ No newline at end of file
diff --git a/examples/csrf/src/main.rs b/examples/csrf/src/main.rs
new file mode 100644
index 0000000..16b31a1
--- /dev/null
+++ b/examples/csrf/src/main.rs
@@ -0,0 +1,59 @@
+use std::convert::Infallible;
+use hyper::service::{service_fn, make_service_fn};
+use hyper::{Method, Server};
+use serde::Deserialize;
+use sputnik::security::CsrfToken;
+use sputnik::{Error, request::{Parts, Body}, response::Response};
+
+async fn route(req: &mut Parts, body: Body) -> Result<Response,Error> {
+ match (req.method(), req.uri().path()) {
+ (&Method::GET, "/form") => get_form(req).await,
+ (&Method::POST, "/form") => post_form(req, body).await,
+ _ => return Err(Error::not_found("page not found".to_owned()))
+ }
+}
+
+async fn get_form(req: &mut Parts) -> Result<Response, Error> {
+ let mut response = Response::new();
+ let csrf_token = CsrfToken::from_parts(req, &mut response);
+ *response.body() = format!("<form method=post>
+ <input name=text>{}<button>Submit</button></form>", csrf_token.html_input()).into();
+ Ok(response)
+}
+
+#[derive(Deserialize)]
+struct FormData {text: String}
+
+async fn post_form(req: &mut Parts, body: Body) -> Result<Response, Error> {
+ let mut response = Response::new();
+ let csrf_token = CsrfToken::from_parts(req, &mut response);
+ let msg: FormData = body.into_form_csrf(&csrf_token).await?;
+ *response.body() = format!("hello {}", msg.text).into();
+ Ok(response)
+}
+
+/// adapt between Hyper's types and Sputnik's convenience types
+async fn service(req: hyper::Request<hyper::Body>) -> Result<hyper::Response<hyper::Body>, Infallible> {
+ let (mut parts, body) = sputnik::request::adapt(req);
+ match route(&mut parts, body).await {
+ Ok(res) => Ok(res.into()),
+ Err(err) => Ok(err.response_builder().body(err.message.into()).unwrap())
+ // you can easily wrap or log errors here
+ }
+}
+
+#[tokio::main]
+async fn main() {
+ let service = make_service_fn(move |_| {
+ async move {
+ Ok::<_, hyper::Error>(service_fn(move |req| {
+ service(req)
+ }))
+ }
+ });
+
+ let addr = ([127, 0, 0, 1], 8000).into();
+ let server = Server::bind(&addr).serve(service);
+ println!("Listening on http://{}", addr);
+ server.await;
+} \ No newline at end of file