hub-sdk 0.3.3

Geeny Linux Hub SDK
// Copyright 2017 Telefónica Germany Next GmbH. See the COPYRIGHT file at
// the top-level directory of this distribution
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! Geeny Hub SDK Error Types
//!
//! These error types are generated by [Error Chain](https://docs.rs/error-chain/).
//! These types can be combined with other crates using `error_chain` in the following way:
//!
//! ```rust
//! #[macro_use]
//! extern crate error_chain;
//! extern crate hub_sdk;
//!
//! mod your_error {
//!     use hub_sdk::errors;
//!
//!     error_chain!{
//!         links {
//!             GeenyHub(errors::Error, errors::ErrorKind);
//!         }
//!     }
//! }
//!
//! fn main() {}
//! ```
//!
//! Additionally, `Error` implements the `Responder` trait from Rocket, and will produce
//! a JSON return value with error code 400 if returned from a route handler in Rocket.

use std::io::Cursor;
use std::fmt::Write;

use log;
use rocket::request::Request;
use rocket::response::{Responder, Response};
use rocket::http::{ContentType, Status};
use mvdb::errors as merr;

use geeny_api::errors as gerr;

// TODO DI-234 - Proper enumeration of errors
error_chain!{
    links {
        Mvdb(merr::Error, merr::ErrorKind);
        GeenyApi(gerr::Error, gerr::ErrorKind);
    }
}

// Implement `Responder` for `error_chain`'s `Error` type
impl<'r> Responder<'r> for Error {
    /// Implement `respond_to` in order to allow route handlers to generate a JSON response
    /// in the case of error. Please see [this blog post](https://jamesmunns.com/update/2017/07/22/rocket-plus-error-chain.html)
    /// for more information
    fn respond_to(self, _: &Request) -> ::std::result::Result<Response<'r>, Status> {
        // Render the whole error chain to a single string
        let mut rslt = String::new();
        write!(rslt, "Error: {}", self).unwrap();

        for ce in self.iter().skip(1) {
            write!(rslt, ", caused by: {}", ce).unwrap();
        }

        log::error!("{}", rslt);

        // Create JSON response
        let resp = json!({
            "status": "failure",
            "message": rslt,
        }).to_string();

        // Respond. The `Ok` here is a bit of a misnomer. It means we
        // successfully created an error response
        Ok(
            Response::build()
                .status(Status::BadRequest)
                .header(ContentType::JSON)
                .sized_body(Cursor::new(resp))
                .finalize(),
        )
    }
}