rouille/try_or_400.rs
1// Copyright (c) 2016 The Rouille developers
2// Licensed under the Apache License, Version 2.0
3// <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
6// at your option. All files in the project carrying such
7// notice may not be copied, modified, or distributed except
8// according to those terms.
9
10//! Everything in this module is private, but is still publicly accessible from the outside
11//! because of the `try_or_400!` macro.
12
13use std::error::Error;
14
15/// This macro assumes that the current function returns a `Response` and takes a `Result`.
16/// If the expression you pass to the macro is an error, then a 400 response is returned.
17///
18/// # Example
19///
20/// ```
21/// # #[macro_use] extern crate rouille;
22/// # fn main() {
23/// use rouille::Request;
24/// use rouille::Response;
25///
26/// fn handle_something(request: &Request) -> Response {
27/// let data = try_or_400!(post_input!(request, {
28/// field1: u32,
29/// field2: String,
30/// }));
31///
32/// Response::text("hello")
33/// }
34/// # }
35/// ```
36#[macro_export]
37macro_rules! try_or_400 {
38 ($result:expr) => {
39 match $result {
40 Ok(r) => r,
41 Err(err) => {
42 let json = $crate::try_or_400::ErrJson::from_err(&err);
43 return $crate::Response::json(&json).with_status_code(400);
44 }
45 }
46 };
47}
48
49#[derive(Serialize)]
50pub struct ErrJson {
51 description: String,
52 cause: Option<Box<ErrJson>>,
53}
54
55impl ErrJson {
56 pub fn from_err<E: ?Sized + Error>(err: &E) -> ErrJson {
57 let cause = err.source().map(ErrJson::from_err).map(Box::new);
58 ErrJson {
59 description: err.to_string(),
60 cause,
61 }
62 }
63}