Skip to content

Commit b6be779

Browse files
committed
Code from first post.
In memory ( HashMap ) store for dinos.
1 parent b5a85a2 commit b6be779

File tree

3 files changed

+225
-0
lines changed

3 files changed

+225
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/target

Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "tide-basic-crud"
3+
version = "0.1.0"
4+
authors = ["Pepo Viola <[email protected]>"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
10+
tide = "0.13.0"
11+
async-std = { version = "1.6.0", features = ["attributes"] }
12+
serde = { version = "1.0.115", features = ["derive"] }
13+
serde_json = "1.0.57"

src/main.rs

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
use async_std::sync::RwLock;
2+
use serde::{Deserialize, Serialize};
3+
use std::collections::hash_map::{Entry, HashMap};
4+
use std::sync::Arc;
5+
use tide::{Body, Request, Response, Server};
6+
7+
#[derive(Clone, Debug)]
8+
struct State {
9+
dinos: Arc<RwLock<HashMap<String, Dino>>>,
10+
}
11+
12+
#[derive(Debug, Clone, Deserialize, Serialize)]
13+
struct Dino {
14+
name: String,
15+
weight: u16,
16+
diet: String,
17+
}
18+
19+
#[derive(Debug, Clone, Deserialize, Serialize)]
20+
struct Dinos {
21+
dinos: Vec<Dino>,
22+
}
23+
24+
#[async_std::main]
25+
async fn main() {
26+
tide::log::start();
27+
let dinos_store = Default::default();
28+
let app = server(dinos_store).await;
29+
30+
app.listen("127.0.0.1:8080").await.unwrap();
31+
}
32+
33+
async fn server(dinos_store: Arc<RwLock<HashMap<String, Dino>>>) -> Server<State> {
34+
let state = State {
35+
dinos: dinos_store, //Default::default(),
36+
};
37+
38+
let mut app = tide::with_state(state);
39+
app.at("/").get(|_| async { Ok("ok") });
40+
41+
app.at("/dinos")
42+
.post(|mut req: Request<State>| async move {
43+
let dino: Dino = req.body_json().await?;
44+
// let get a mut ref of our store ( hashMap )
45+
let mut dinos = req.state().dinos.write().await;
46+
dinos.insert(String::from(&dino.name), dino.clone());
47+
println!("{:?}", dinos);
48+
let mut res = Response::new(201);
49+
res.set_body(Body::from_json(&dino)?);
50+
Ok(res)
51+
})
52+
.get(|req: Request<State>| async move {
53+
let dinos = req.state().dinos.read().await;
54+
// get all the dinos as a vector
55+
let dinos_vec: Vec<Dino> = dinos.values().cloned().collect();
56+
let mut res = Response::new(200);
57+
res.set_body(Body::from_json(&dinos_vec)?);
58+
Ok(res)
59+
});
60+
app.at("/dinos/:name")
61+
.get(|req: Request<State>| async move {
62+
let mut dinos = req.state().dinos.write().await;
63+
let key: String = req.param("name")?;
64+
let res = match dinos.entry(key) {
65+
Entry::Vacant(_entry) => Response::new(404),
66+
Entry::Occupied(entry) => {
67+
let mut res = Response::new(200);
68+
res.set_body(Body::from_json(&entry.get())?);
69+
res
70+
}
71+
};
72+
Ok(res)
73+
})
74+
.put(|mut req: Request<State>| async move {
75+
let dino_update: Dino = req.body_json().await?;
76+
let mut dinos = req.state().dinos.write().await;
77+
let key: String = req.param("name")?;
78+
let res = match dinos.entry(key) {
79+
Entry::Vacant(_entry) => Response::new(404),
80+
Entry::Occupied(mut entry) => {
81+
*entry.get_mut() = dino_update;
82+
let mut res = Response::new(200);
83+
res.set_body(Body::from_json(&entry.get())?);
84+
res
85+
}
86+
};
87+
Ok(res)
88+
})
89+
.delete(|req: Request<State>| async move {
90+
let mut dinos = req.state().dinos.write().await;
91+
let key: String = req.param("name")?;
92+
let deleted = dinos.remove(&key);
93+
let res = match deleted {
94+
None => Response::new(404),
95+
Some(_) => Response::new(204),
96+
};
97+
Ok(res)
98+
});
99+
100+
app
101+
}
102+
103+
#[async_std::test]
104+
async fn index_page() -> tide::Result<()> {
105+
use tide::http::{Method, Request, Response, Url};
106+
107+
let dinos_store = Default::default();
108+
let app = server(dinos_store).await;
109+
let url = Url::parse("https://example.com").unwrap();
110+
let req = Request::new(Method::Get, url);
111+
let mut res: Response = app.respond(req).await?;
112+
assert_eq!("ok", res.body_string().await?);
113+
Ok(())
114+
}
115+
116+
#[async_std::test]
117+
async fn list_dinos() -> tide::Result<()> {
118+
use tide::http::{Method, Request, Response, Url};
119+
120+
let dino = Dino {
121+
name: String::from("test"),
122+
weight: 50,
123+
diet: String::from("carnivorous"),
124+
};
125+
126+
let mut dinos_store = HashMap::new();
127+
dinos_store.insert(dino.name.clone(), dino);
128+
let dinos: Vec<Dino> = dinos_store.values().cloned().collect();
129+
let dinos_as_json_string = serde_json::to_string(&dinos)?;
130+
131+
let state = Arc::new(RwLock::new(dinos_store));
132+
let app = server(state).await;
133+
134+
let url = Url::parse("https://example.com/dinos").unwrap();
135+
let req = Request::new(Method::Get, url);
136+
let mut res: Response = app.respond(req).await?;
137+
let v = res.body_string().await?;
138+
assert_eq!(dinos_as_json_string, v);
139+
Ok(())
140+
}
141+
142+
#[async_std::test]
143+
async fn create_dino() -> tide::Result<()> {
144+
use tide::http::{Method, Request, Response, Url};
145+
146+
let dino = Dino {
147+
name: String::from("test"),
148+
weight: 50,
149+
diet: String::from("carnivorous"),
150+
};
151+
152+
let dinos_store = HashMap::new();
153+
154+
let state = Arc::new(RwLock::new(dinos_store));
155+
let app = server(state).await;
156+
157+
let url = Url::parse("https://example.com/dinos").unwrap();
158+
let mut req = Request::new(Method::Post, url);
159+
req.set_body(serde_json::to_string(&dino)?);
160+
let res: Response = app.respond(req).await?;
161+
assert_eq!(201, res.status());
162+
Ok(())
163+
}
164+
165+
#[async_std::test]
166+
async fn update_dino() -> tide::Result<()> {
167+
use tide::http::{Method, Request, Response, Url};
168+
169+
let dino = Dino {
170+
name: String::from("test"),
171+
weight: 500,
172+
diet: String::from("carnivorous"),
173+
};
174+
175+
let dinos_as_json_string = serde_json::to_string(&dino)?;
176+
let mut dinos_store = HashMap::new();
177+
dinos_store.insert(dino.name.clone(), dino);
178+
179+
let state = Arc::new(RwLock::new(dinos_store));
180+
let app = server(state).await;
181+
182+
let url = Url::parse("https://example.com/dinos/test").unwrap();
183+
let mut req = Request::new(Method::Put, url);
184+
req.set_body(dinos_as_json_string);
185+
let res: Response = app.respond(req).await?;
186+
assert_eq!(200, res.status());
187+
Ok(())
188+
}
189+
190+
#[async_std::test]
191+
async fn delete_dino() -> tide::Result<()> {
192+
use tide::http::{Method, Request, Response, Url};
193+
194+
let dino = Dino {
195+
name: String::from("test"),
196+
weight: 50,
197+
diet: String::from("carnivorous"),
198+
};
199+
200+
let mut dinos_store = HashMap::new();
201+
dinos_store.insert(dino.name.clone(), dino);
202+
203+
let state = Arc::new(RwLock::new(dinos_store));
204+
let app = server(state).await;
205+
206+
let url = Url::parse("https://example.com/dinos/test").unwrap();
207+
let req = Request::new(Method::Delete, url);
208+
let res: Response = app.respond(req).await?;
209+
assert_eq!(204, res.status());
210+
Ok(())
211+
}

0 commit comments

Comments
 (0)