/
errors.rs
70 lines (59 loc) · 2.08 KB
/
errors.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
#![deny(warnings)]
use serde_derive::Serialize;
use warp::http::StatusCode;
use warp::{reject, Filter, Rejection, Reply};
/// A custom `Reject` type.
#[derive(Debug)]
enum Error {
Oops,
Nope,
}
impl reject::Reject for Error {}
/// A serialized message to report in JSON format.
#[derive(Serialize)]
struct ErrorMessage<'a> {
code: u16,
message: &'a str,
}
#[tokio::main]
async fn main() {
let hello = warp::path::end().map(warp::reply);
let oops = warp::path("oops").and_then(|| async {
Err::<StatusCode, _>(reject::custom(Error::Oops))
});
let nope = warp::path("nope").and_then(|| async {
Err::<StatusCode, _>(reject::custom(Error::Nope))
});
let routes = warp::get()
.and(hello.or(oops).or(nope))
.recover(customize_error);
warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
}
// This function receives a `Rejection` and tries to return a custom
// value, othewise simply passes the rejection along.
async fn customize_error(err: Rejection) -> Result<impl Reply, Rejection> {
if let Some(err) = err.find::<Error>() {
let (code, msg) = match err {
Error::Nope => (StatusCode::BAD_REQUEST, "Nope!"),
Error::Oops => (StatusCode::INTERNAL_SERVER_ERROR, ":fire: this is fine"),
};
let json = warp::reply::json(&ErrorMessage {
code: code.as_u16(),
message: msg,
});
Ok(warp::reply::with_status(json, code))
} else if let Some(_) = err.find::<warp::reject::MethodNotAllowed>() {
// We can handle a specific error, here METHOD_NOT_ALLOWED,
// and render it however we want
let code = StatusCode::METHOD_NOT_ALLOWED;
let json = warp::reply::json(&ErrorMessage {
code: code.as_u16(),
message: "oops, you aren't allowed to use this method.".into(),
});
Ok(warp::reply::with_status(json, code))
} else {
// Could be a NOT_FOUND, or any other internal error... here we just
// let warp use its default rendering.
Err(err)
}
}