Rocket/examples/forms/src/main.rs

98 lines
2.4 KiB
Rust

#[macro_use] extern crate rocket;
use rocket::time::Date;
use rocket::http::{Status, ContentType};
use rocket::form::{Form, Contextual, FromForm, FromFormField, Context};
use rocket::fs::{FileServer, TempFile, relative};
use rocket_dyn_templates::Template;
#[derive(Debug, FromForm)]
struct Password<'v> {
#[field(validate = len(6..))]
#[field(validate = eq(self.second))]
#[allow(unused)]
first: &'v str,
#[allow(unused)]
#[field(validate = eq(self.first))]
second: &'v str,
}
#[derive(Debug, FromFormField)]
enum Rights {
Public,
Reserved,
Exclusive,
}
#[derive(Debug, FromFormField)]
enum Category {
Biology,
Chemistry,
Physics,
#[field(value = "CS")]
ComputerScience,
}
#[derive(Debug, FromForm)]
#[allow(dead_code)]
struct Submission<'v> {
#[field(validate = len(1..))]
title: &'v str,
date: Date,
#[field(validate = len(1..=250))]
r#abstract: &'v str,
#[field(validate = ext(ContentType::PDF))]
file: TempFile<'v>,
#[field(validate = len(1..))]
category: Vec<Category>,
rights: Rights,
ready: bool,
}
#[derive(Debug, FromForm)]
#[allow(dead_code)]
struct Account<'v> {
#[field(validate = len(1..))]
name: &'v str,
password: Password<'v>,
#[field(validate = contains('@').or_else(msg!("invalid email address")))]
email: &'v str,
}
#[derive(Debug, FromForm)]
#[allow(dead_code)]
struct Submit<'v> {
account: Account<'v>,
submission: Submission<'v>,
}
#[get("/")]
fn index() -> Template {
Template::render("index", &Context::default())
}
// NOTE: We use `Contextual` here because we want to collect all submitted form
// fields to re-render forms with submitted values on error. If you have no such
// need, do not use `Contextual`. Use the equivalent of `Form<Submit<'_>>`.
#[post("/", data = "<form>")]
fn submit<'r>(form: Form<Contextual<'r, Submit<'r>>>) -> (Status, Template) {
let template = match form.value {
Some(ref submission) => {
println!("submission: {:#?}", submission);
Template::render("success", &form.context)
}
None => Template::render("index", &form.context),
};
(form.context.status(), template)
}
#[launch]
fn rocket() -> _ {
rocket::build()
.mount("/", routes![index, submit])
.attach(Template::fairing())
.mount("/", FileServer::from(relative!("/static")))
}