Skip to content

Instantly share code, notes, and snippets.

@nathansamson
Created August 10, 2019 13:51
Show Gist options
  • Save nathansamson/85f7ccb52044f45aa85f8faf6ca9f1af to your computer and use it in GitHub Desktop.
Save nathansamson/85f7ccb52044f45aa85f8faf6ca9f1af to your computer and use it in GitHub Desktop.
Basic form handing in Rocket
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use] extern crate rocket;
use rocket::request::{Form, FromFormValue};
use rocket::http::RawStr;
use rocket_contrib::serve::StaticFiles;
use rocket_contrib::templates::Template;
use serde::Serialize;
#[derive(Serialize)]
struct NullContext { }
#[derive(Serialize)]
struct LoginFormContext {
login_form_url: String,
login_fields: Option<LoginFields>,
}
#[derive(Clone)]
struct ValidEmail<'r>(&'r str);
#[derive(Serialize)]
struct LoginFields {
email: String,
email_error: Option<String>,
password: String,
password_error: Option<String>,
}
#[derive(Clone)]
struct ErrWithOriginal(String, String);
impl std::fmt::Debug for ErrWithOriginal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "ErrWithOriginal {{ err: {}, original: {} }}", self.0, self.1)
}
}
#[derive(FromForm)]
struct LoginForm<'r> {
email: Result<ValidEmail<'r>, ErrWithOriginal>,
password: String,
}
impl<'v> FromFormValue<'v> for ValidEmail<'v> {
type Error = ErrWithOriginal;
fn from_form_value(v: &'v RawStr) -> Result<Self, ErrWithOriginal> {
println!("Incoming email {}", v.url_decode().unwrap());
if v.url_decode().unwrap() == "nathan@nathansamson.be" {
Ok(ValidEmail(v.as_str()))
} else {
Err(ErrWithOriginal("Not me".to_string(), v.url_decode().unwrap().to_string()))
}
}
}
#[post("/login", data = "<login>")]
fn login(login: Form<LoginForm>) -> Template {
if login.email.is_ok() {
let context = NullContext { };
Template::render("index/dashboard", &context)
} else {
let context = LoginFormContext {
login_form_url: uri!(login).to_string(),
login_fields: Some(LoginFields {
email: if login.email.is_ok() { (login.email.clone().unwrap().0).to_string() } else { (login.email.clone().err().unwrap()).1 },
email_error: if login.email.is_err() { Some((login.email.clone().err().unwrap()).0) } else { None },
password: login.password.clone(),
password_error: None }),
};
Template::render("index/login", &context)
}
}
#[get("/")]
fn index() -> Template {
let context = LoginFormContext {
login_form_url: uri!(login).to_string(),
login_fields: None,
};
Template::render("index/login", &context)
}
fn main() {
rocket::ignite().
attach(Template::fairing()).
mount("/public", StaticFiles::from("./dist")).
mount("/", routes![index, login]).launch();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment