Port to Rocket 0.5.0-rc1

The rocket-contrib crate has been dropped by upstream.
The serde and serde_json crates are only necessary for the tests.
This commit is contained in:
Paul van Tilburg 2021-06-13 21:59:22 +02:00
parent e79940fe11
commit c3ae8ca62a
Signed by: paul
GPG Key ID: C6DE073EDA9EEC4D
9 changed files with 1111 additions and 574 deletions

1532
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -14,13 +14,10 @@ edition = "2018"
comrak = "0.7.0" comrak = "0.7.0"
glob = "0.3.0" glob = "0.3.0"
Inflector = "*" Inflector = "*"
rocket = "0.4.3" rocket = { version = "0.5.0-rc.1", features = ["json"] }
serde = "1.0" rocket_dyn_templates = { version = "0.1.0-rc.1", features = ["tera"] }
serde_derive = "1.0"
serde_json = "1.0"
toml = "0.5" toml = "0.5"
[dependencies.rocket_contrib] [dev-dependencies]
version = "0.4.3" serde = "1.0"
default-features = false serde_json = "1.0"
features = ["json", "tera_templates"]

View File

@ -1,3 +1,3 @@
[development] [debug]
address = "0.0.0.0" address = "0.0.0.0"
port = 3000 port = 3000

View File

@ -1,11 +1,13 @@
use super::super::Config;
use super::super::NoteStore;
use rocket::{get, State};
use rocket_contrib::templates::Template;
use serde_derive::Serialize;
use std::collections::HashMap; use std::collections::HashMap;
use rocket::serde::Serialize;
use rocket::{get, State};
use rocket_dyn_templates::Template;
use super::super::{Config, NoteStore};
#[derive(Serialize)] #[derive(Serialize)]
#[serde(crate = "rocket::serde")]
struct IndexTemplateContext<'a> { struct IndexTemplateContext<'a> {
app_version: &'a str, app_version: &'a str,
notes: Vec<HashMap<&'a str, &'a str>>, notes: Vec<HashMap<&'a str, &'a str>>,
@ -13,7 +15,7 @@ struct IndexTemplateContext<'a> {
} }
#[get("/")] #[get("/")]
pub(crate) fn index(notes: State<NoteStore>, config: State<Config>) -> Template { pub(crate) async fn index(notes: &State<NoteStore>, config: &State<Config>) -> Template {
let notes = notes.read().unwrap(); let notes = notes.read().unwrap();
let mut note_kvs = vec![]; let mut note_kvs = vec![];
for note in notes.iter() { for note in notes.iter() {
@ -34,17 +36,17 @@ pub(crate) fn index(notes: State<NoteStore>, config: State<Config>) -> Template
mod tests { mod tests {
use rocket; use rocket;
use rocket::http::{Accept, Status}; use rocket::http::{Accept, Status};
use rocket::local::Client; use rocket::local::blocking::Client;
#[test] #[test]
fn index() { fn index() {
let client = Client::new(crate::rocket(Some("test"))).unwrap(); let client = Client::untracked(crate::rocket(Some("test"))).unwrap();
// Try to get the index and verify the body // Try to get the index and verify the body
let mut res = client.get("/").header(Accept::HTML).dispatch(); let res = client.get("/").header(Accept::HTML).dispatch();
assert_eq!(res.status(), Status::Ok); assert_eq!(res.status(), Status::Ok);
let body = res.body_string().unwrap(); let body = res.into_string().unwrap();
println!("body: {}", body); println!("body: {}", body);
assert!(body.contains("<span id=\"note-name\">Test</span>")); assert!(body.contains("<span id=\"note-name\">Test</span>"));
} }

View File

@ -1,3 +1,2 @@
pub mod home; pub mod home;
pub mod note; pub mod note;
pub mod static_files;

View File

@ -1,33 +1,34 @@
use rocket::serde::json::Json;
use rocket::{get, put, State};
use super::super::models::note::Note; use super::super::models::note::Note;
use super::super::NoteStore; use super::super::NoteStore;
use rocket::{get, put, State};
use rocket_contrib::json::Json;
#[get("/", format = "application/json")] #[get("/", format = "application/json")]
pub(crate) fn index(notes: State<NoteStore>) -> Option<Json<Vec<Note>>> { pub(crate) async fn index(notes: &State<NoteStore>) -> Option<Json<Vec<Note>>> {
let notes = notes.read().unwrap(); let notes = notes.read().unwrap();
Some(Json(notes.clone())) Some(Json(notes.clone()))
} }
#[get("/<note_id>", format = "text/html")] #[get("/<note_id>", format = "text/html")]
pub(crate) fn show_html(note_id: String, notes: State<NoteStore>) -> Option<String> { pub(crate) async fn show_html(note_id: String, notes: &State<NoteStore>) -> Option<String> {
let notes = notes.read().unwrap(); let notes = notes.read().unwrap();
let note = notes.iter().find(|note| note.id == note_id)?; let note = notes.iter().find(|note| note.id == note_id)?;
Some(note.to_html()) Some(note.to_html())
} }
#[get("/<note_id>", format = "application/json", rank = 2)] #[get("/<note_id>", format = "application/json", rank = 2)]
pub(crate) fn show_json(note_id: String, notes: State<NoteStore>) -> Option<Json<Note>> { pub(crate) async fn show_json(note_id: String, notes: &State<NoteStore>) -> Option<Json<Note>> {
let notes = notes.read().unwrap(); let notes = notes.read().unwrap();
let note = notes.iter().find(|note| note.id == note_id)?; let note = notes.iter().find(|note| note.id == note_id)?;
Some(Json(note.clone())) Some(Json(note.clone()))
} }
#[put("/<note_id>", format = "application/json", data = "<new_note>")] #[put("/<note_id>", format = "application/json", data = "<new_note>")]
pub(crate) fn update( pub(crate) async fn update(
note_id: String, note_id: String,
new_note: Json<Note>, new_note: Json<Note>,
notes: State<NoteStore>, notes: &State<NoteStore>,
) -> Option<Json<Note>> { ) -> Option<Json<Note>> {
let mut notes = notes.write().unwrap(); let mut notes = notes.write().unwrap();
let note = notes.iter_mut().find(|note| note.id == note_id)?; let note = notes.iter_mut().find(|note| note.id == note_id)?;
@ -37,21 +38,22 @@ pub(crate) fn update(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use rocket; use rocket;
use rocket::http::{Accept, ContentType, Status}; use rocket::http::{Accept, ContentType, Status};
use rocket::local::Client; use rocket::local::blocking::Client;
use serde_json::{self, json}; use serde_json::{self, json};
use super::*;
#[test] #[test]
fn index() { fn index() {
let client = Client::new(crate::rocket(Some("test"))).unwrap(); let client = Client::untracked(crate::rocket(Some("test"))).unwrap();
// Try to get all the notes // Try to get all the notes
let mut res = client.get("/notes").header(Accept::JSON).dispatch(); let res = client.get("/notes").header(Accept::JSON).dispatch();
assert_eq!(res.status(), Status::Ok); assert_eq!(res.status(), Status::Ok);
let body = res.body_string().unwrap(); let body = res.into_string().unwrap();
let notes = serde_json::from_str::<Vec<Note>>(body.as_str()).unwrap(); let notes = serde_json::from_str::<Vec<Note>>(body.as_str()).unwrap();
assert_eq!(notes[0].id, "test"); assert_eq!(notes[0].id, "test");
assert_eq!(notes[0].index, 0); assert_eq!(notes[0].index, 0);
@ -70,13 +72,13 @@ mod tests {
#[test] #[test]
fn show_html() { fn show_html() {
let client = Client::new(crate::rocket(Some("test"))).unwrap(); let client = Client::untracked(crate::rocket(Some("test"))).unwrap();
// Try to get the note and verify the body // Try to get the note and verify the body
let mut res = client.get("/notes/test").header(Accept::HTML).dispatch(); let res = client.get("/notes/test").header(Accept::HTML).dispatch();
assert_eq!(res.status(), Status::Ok); assert_eq!(res.status(), Status::Ok);
let body = res.body_string().unwrap(); let body = res.into_string().unwrap();
assert_eq!( assert_eq!(
body, body,
r#"<p>This is a test note</p> r#"<p>This is a test note</p>
@ -91,13 +93,13 @@ mod tests {
#[test] #[test]
fn show_json() { fn show_json() {
let client = Client::new(crate::rocket(Some("test"))).unwrap(); let client = Client::untracked(crate::rocket(Some("test"))).unwrap();
// Try to get the note and verify the body // Try to get the note and verify the body
let mut res = client.get("/notes/test").header(Accept::JSON).dispatch(); let res = client.get("/notes/test").header(Accept::JSON).dispatch();
assert_eq!(res.status(), Status::Ok); assert_eq!(res.status(), Status::Ok);
let body = res.body_string().unwrap(); let body = res.into_string().unwrap();
let note = serde_json::from_str::<Note>(body.as_str()).unwrap(); let note = serde_json::from_str::<Note>(body.as_str()).unwrap();
assert_eq!(note.id, "test"); assert_eq!(note.id, "test");
assert_eq!(note.index, 0); assert_eq!(note.index, 0);
@ -118,14 +120,14 @@ mod tests {
#[test] #[test]
fn update() { fn update() {
let client = Client::new(crate::rocket(Some("test"))).unwrap(); let client = Client::untracked(crate::rocket(Some("test"))).unwrap();
// Try to get the note and determine what to change it to // Try to get the note and determine what to change it to
let mut res = client let res = client
.get("/notes/updatable") .get("/notes/updatable")
.header(Accept::JSON) .header(Accept::JSON)
.dispatch(); .dispatch();
let body = res.body_string().unwrap(); let body = res.into_string().unwrap();
let note = serde_json::from_str::<Note>(body.as_str()).unwrap(); let note = serde_json::from_str::<Note>(body.as_str()).unwrap();
assert_eq!(note.data, "Some content"); assert_eq!(note.data, "Some content");
@ -149,11 +151,11 @@ mod tests {
.dispatch(); .dispatch();
assert_eq!(res.status(), Status::Ok); assert_eq!(res.status(), Status::Ok);
let mut res = client let res = client
.get("/notes/updatable") .get("/notes/updatable")
.header(Accept::JSON) .header(Accept::JSON)
.dispatch(); .dispatch();
let body = res.body_string().unwrap(); let body = res.into_string().unwrap();
let note = serde_json::from_str::<Note>(body.as_str()).unwrap(); let note = serde_json::from_str::<Note>(body.as_str()).unwrap();
assert_eq!(note.data, new_data); assert_eq!(note.data, new_data);

View File

@ -1,28 +0,0 @@
use rocket::get;
use rocket::response::NamedFile;
use std::path::{Path, PathBuf};
#[get("/<path..>", rank = 5)]
pub(crate) fn all(path: PathBuf) -> Option<NamedFile> {
NamedFile::open(
Path::new(env!("CARGO_MANIFEST_DIR"))
.join("static")
.join(path),
)
.ok()
}
#[cfg(test)]
mod tests {
use rocket::http::Status;
use rocket::local::Client;
#[test]
fn all() {
let client = Client::new(crate::rocket(Some("test"))).unwrap();
// Try to get the main JavaScript file
let res = client.get("/js/pinboard.js").dispatch();
assert_eq!(res.status(), Status::Ok);
}
}

View File

@ -1,8 +1,9 @@
#![feature(proc_macro_hygiene, decl_macro)]
use rocket::{routes, Rocket};
use serde_derive::Deserialize;
use std::sync::RwLock; use std::sync::RwLock;
use rocket::fs::{relative, FileServer};
use rocket::serde::Deserialize;
use rocket::{routes, Build, Rocket};
use rocket_dyn_templates::Template;
use toml; use toml;
mod handlers; mod handlers;
@ -11,11 +12,12 @@ mod models;
type NoteStore = RwLock<Vec<models::note::Note>>; type NoteStore = RwLock<Vec<models::note::Note>>;
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct Config { pub struct Config {
title: String, title: String,
} }
fn rocket(notes_path: Option<&str>) -> Rocket { fn rocket(notes_path: Option<&str>) -> Rocket<Build> {
use std::fs::File; use std::fs::File;
use std::io::prelude::*; use std::io::prelude::*;
use std::path::Path; use std::path::Path;
@ -32,13 +34,11 @@ fn rocket(notes_path: Option<&str>) -> Rocket {
let notes = models::note::Note::load_all(notes_path); let notes = models::note::Note::load_all(notes_path);
rocket::ignite() rocket::build()
.manage(RwLock::new(notes)) .manage(RwLock::new(notes))
.manage(config) .manage(config)
.mount( .mount("/", FileServer::from(relative!("static")))
"/", .mount("/", routes![handlers::home::index])
routes![handlers::home::index, handlers::static_files::all],
)
.mount( .mount(
"/notes", "/notes",
routes![ routes![
@ -48,9 +48,12 @@ fn rocket(notes_path: Option<&str>) -> Rocket {
handlers::note::update handlers::note::update
], ],
) )
.attach(rocket_contrib::templates::Template::fairing()) .attach(Template::fairing())
} }
fn main() { #[rocket::main]
rocket(None).launch(); async fn main() -> Result<(), rocket::Error> {
rocket(None).launch().await?;
Ok(())
} }

View File

@ -1,13 +1,15 @@
use comrak;
use glob::glob;
use inflector::Inflector;
use serde_derive::{Deserialize, Serialize};
use std::fs::File; use std::fs::File;
use std::io::prelude::*; use std::io::prelude::*;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::SystemTime; use std::time::SystemTime;
use comrak;
use glob::glob;
use inflector::Inflector;
use rocket::serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
/// Structure for representing a wish note /// Structure for representing a wish note
pub struct Note { pub struct Note {
/// The ID of the note (unique string) /// The ID of the note (unique string)