aboutsummaryrefslogtreecommitdiff
path: root/examples/csrf/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'examples/csrf/src/main.rs')
-rw-r--r--examples/csrf/src/main.rs59
1 files changed, 59 insertions, 0 deletions
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