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}