1 #![feature(proc_macro_hygiene)]
2 
3 #[macro_use] extern crate rocket;
4 #[macro_use] extern crate rocket_contrib;
5 #[macro_use] extern crate serde_derive;
6 
7 #[cfg(test)] mod tests;
8 
9 use std::sync::Mutex;
10 use std::collections::HashMap;
11 
12 use rocket::State;
13 use rocket_contrib::json::{Json, JsonValue};
14 
15 // The type to represent the ID of a message.
16 type ID = usize;
17 
18 // We're going to store all of the messages here. No need for a DB.
19 type MessageMap = Mutex<HashMap<ID, String>>;
20 
21 #[derive(Serialize, Deserialize)]
22 struct Message {
23     id: Option<ID>,
24     contents: String
25 }
26 
27 // TODO: This example can be improved by using `route` with multiple HTTP verbs.
28 #[post("/<id>", format = "json", data = "<message>")]
new(id: ID, message: Json<Message>, map: State<'_, MessageMap>) -> JsonValue29 fn new(id: ID, message: Json<Message>, map: State<'_, MessageMap>) -> JsonValue {
30     let mut hashmap = map.lock().expect("map lock.");
31     if hashmap.contains_key(&id) {
32         json!({
33             "status": "error",
34             "reason": "ID exists. Try put."
35         })
36     } else {
37         hashmap.insert(id, message.0.contents);
38         json!({ "status": "ok" })
39     }
40 }
41 
42 #[put("/<id>", format = "json", data = "<message>")]
update(id: ID, message: Json<Message>, map: State<'_, MessageMap>) -> Option<JsonValue>43 fn update(id: ID, message: Json<Message>, map: State<'_, MessageMap>) -> Option<JsonValue> {
44     let mut hashmap = map.lock().unwrap();
45     if hashmap.contains_key(&id) {
46         hashmap.insert(id, message.0.contents);
47         Some(json!({ "status": "ok" }))
48     } else {
49         None
50     }
51 }
52 
53 #[get("/<id>", format = "json")]
get(id: ID, map: State<'_, MessageMap>) -> Option<Json<Message>>54 fn get(id: ID, map: State<'_, MessageMap>) -> Option<Json<Message>> {
55     let hashmap = map.lock().unwrap();
56     hashmap.get(&id).map(|contents| {
57         Json(Message {
58             id: Some(id),
59             contents: contents.clone()
60         })
61     })
62 }
63 
64 #[catch(404)]
not_found() -> JsonValue65 fn not_found() -> JsonValue {
66     json!({
67         "status": "error",
68         "reason": "Resource was not found."
69     })
70 }
71 
rocket() -> rocket::Rocket72 fn rocket() -> rocket::Rocket {
73     rocket::ignite()
74         .mount("/message", routes![new, update, get])
75         .register(catchers![not_found])
76         .manage(Mutex::new(HashMap::<ID, String>::new()))
77 }
78 
main()79 fn main() {
80     rocket().launch();
81 }
82