-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.rs
112 lines (96 loc) · 3.1 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use async_std;
use ergolib;
use tide::{Body, Request, Response};
#[derive(Debug, serde::Deserialize, serde::Serialize)]
struct Counter {
count: usize,
}
struct AppError(ergolib::Error);
impl std::error::Error for AppError {}
impl std::fmt::Debug for AppError {
// we have to manually define Debug becuase the external library
// didn't derive it
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.0 {
ergolib::Error::DontLikeIt => write!(f, "Don't like it"),
ergolib::Error::DivisionByZero => write!(f, "Division by zero"),
}
}
}
impl std::fmt::Display for AppError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
impl From<ergolib::Error> for AppError {
fn from(e: ergolib::Error) -> Self {
Self(e)
}
}
// this could just as easily be inlined in the middleware, or a normal
// method on AppError
impl Into<Response> for &AppError {
fn into(self) -> Response {
match self.0 {
ergolib::Error::DontLikeIt => {
let mut res = Response::new(500);
res.set_body("The server doesn't like this number");
res
}
ergolib::Error::DivisionByZero => {
let mut res = Response::new(422);
res.set_body("count can't be zero");
res
}
}
}
}
//only renamed for clarity
type AppResult = std::result::Result<Counter, AppError>;
//unchanged
fn handle42(mut counter: Counter) -> AppResult {
counter.count -= 1;
counter.count = ergolib::nth42(counter.count)?;
Ok(counter)
}
//unchanged
fn handle1337(mut counter: Counter) -> AppResult {
counter.count -= 1;
counter.count = ergolib::nth1337(counter.count)?;
Ok(counter)
}
#[async_std::main]
async fn main() -> tide::Result<()> {
let mut app = tide::new();
app.middleware(tide::After(|res: tide::Response| async move {
if let Some(e) = res.downcast_error::<AppError>() {
Ok(e.into())
} else if let Some(e) = res.downcast_error::<serde_yaml::Error>() {
let mut res = Response::new(422);
res.set_body(format!("YAML error: {}", e));
Ok(res)
} else {
Ok(res)
}
}));
app.at("/42").post(|mut req: Request<()>| async move {
let body = req.body_string().await?;
let mut counter: Counter = serde_yaml::from_str(&body)?;
println!("[42] count is {}", counter.count);
counter = handle42(counter)?;
let mut res = Response::new(200);
res.set_body(Body::from_json(&counter)?);
Ok(res)
});
app.at("/1337").post(|mut req: Request<()>| async move {
let body = req.body_string().await?;
let mut counter: Counter = serde_yaml::from_str(&body)?;
println!("[1337] count is {}", counter.count);
counter = handle1337(counter)?;
let mut res = Response::new(200);
res.set_body(Body::from_json(&counter)?);
Ok(res)
});
app.listen("127.0.0.1:8080").await?;
Ok(())
}