hirust-resp 0.1.0

A Rust Responder Lib
Documentation
use actix_web::body::BoxBody;
use actix_web::http::header::ContentType;
use actix_web::http::StatusCode;
use actix_web::{error, HttpRequest, HttpResponse, Responder};
use serde::Serialize;
use std::fmt::{Debug, Display, Formatter};

pub fn success<T: Sized + Serialize + Default>(data: Option<T>) -> Response<T> {
    Response{
        data,
        msg: String::from("成功"),
        code: 200 }
}

pub fn success_respond_to<T: Sized + Serialize + Default>(req: &HttpRequest, data: Option<T>) -> HttpResponse<<Response<T> as Responder>::Body> {
    success(data).respond_to(req)
}

pub fn error<T: Sized + Serialize + Default>(data: Option<T>) -> Response<T> {
    Response{
        data,
        msg: String::from("失败"),
        ..Default::default() }
}

pub fn error_respond_to<T: Sized + Serialize + Default>(req: &HttpRequest, data: Option<T>) -> HttpResponse<<Response<T> as Responder>::Body> {
    error(data).respond_to(req)
}

pub fn throw(req: &HttpRequest, ec: ErrorCode) -> HttpResponse<<Response<ErrorCode> as Responder>::Body> {
    Response::<ErrorCode>{
        data: None,
        msg: ec.message().parse().unwrap(),
        code: ec.code() as i32
    }.respond_to(req)
}

pub fn throw_tips(req: &HttpRequest, ec: ErrorCode, tips: &'static str) -> HttpResponse<<Response<ErrorCode> as Responder>::Body> {
    Response::<ErrorCode>{
        data: None,
        msg: ec.message().replace("%s", tips).parse().unwrap(),
        code: ec.code() as i32
    }.respond_to(req)
}

pub fn unauthorized<T: Sized + Serialize + Default>(req: &HttpRequest) -> HttpResponse<<Response<T> as Responder>::Body> {
    let r: Response<String> = Response{
        data: None,
        msg: String::from("无权限访问"),
        ..Default::default() };
    r.respond_to(req)
}

#[derive(Serialize, Default)]
pub struct Response<T>
where
    T: Sized + Serialize,
{
    pub code: i32,
    pub data: Option<T>,
    pub msg: String,
}

// Responder
impl<T> Responder for Response<T>
where
    T: Sized + Serialize,
{
    type Body = BoxBody;

    fn respond_to(self, _req: &HttpRequest) -> HttpResponse<Self::Body> {
        let body = serde_json::to_string(&self).unwrap();

        // Create response and set content type
        HttpResponse::Ok()
            .content_type(ContentType::json())
            .body(body)
    }
}

impl<T:  Serialize> Display for Response<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let serialized = serde_json::to_string(&self).unwrap();
        write!(f, "{}", serialized)
    }
}

impl<T: Serialize> Debug for Response<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let serialized = serde_json::to_string(&self).unwrap();
        write!(f, "{}", serialized)
    }
}

impl<T: Serialize> error::ResponseError for Response<T> {
    fn error_response(&self) -> HttpResponse {
        HttpResponse::build(self.status_code())
            .insert_header(ContentType::json())
            .body(self.to_string())
    }

    fn status_code(&self) -> StatusCode {
        // match *self {
        //     ErrorCode::InternalError => StatusCode::INTERNAL_SERVER_ERROR,
        //     ErrorCode::BadClientData => StatusCode::BAD_REQUEST,
        //     ErrorCode::Timeout => StatusCode::GATEWAY_TIMEOUT,
        // }
        StatusCode::OK
    }
}

#[derive(Serialize, Default, Debug)]
pub struct ErrorCode {
    pub code: i64,
    pub message: &'static str,
}

impl ErrorCode {
    #[allow(dead_code)]
    pub fn code(&self) -> i64 {
        self.code
    }

    #[allow(dead_code)]
    pub fn code_string(&self) -> Option<String> {
        Some(format!("{}", self.code))
    }

    #[allow(dead_code)]
    pub fn message(&self) -> &'static str {
        &self.message
    }

    #[allow(dead_code)]
    pub fn throw_tips(&self, req: &HttpRequest, tips: &'static str) -> HttpResponse<<Response<ErrorCode> as Responder>::Body> {
        Response::<ErrorCode>{
            data: None,
            msg: self.message().replace("%s", tips).parse().unwrap(),
            code: self.code() as i32
        }.respond_to(req)
    }

    #[allow(dead_code)]
    pub fn throw(&self, req: &HttpRequest) -> HttpResponse<<Response<ErrorCode> as Responder>::Body> {
        Response::<ErrorCode>{
            data: None,
            msg: self.message().parse().unwrap(),
            code: self.code() as i32
        }.respond_to(req)
    }
}

impl Display for ErrorCode {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "({}, {})", self.code, self.message)
    }
}

impl error::ResponseError for ErrorCode {
    fn error_response(&self) -> HttpResponse {
        HttpResponse::build(self.status_code())
            .insert_header(ContentType::html())
            .body(self.to_string())
    }

    fn status_code(&self) -> StatusCode {
        // match *self {
        //     ErrorCode::InternalError => StatusCode::INTERNAL_SERVER_ERROR,
        //     ErrorCode::BadClientData => StatusCode::BAD_REQUEST,
        //     ErrorCode::Timeout => StatusCode::GATEWAY_TIMEOUT,
        // }
        StatusCode::BAD_REQUEST
    }
}

#[allow(dead_code)]
pub trait Auth {
    fn response(&self) -> Response<Vec<i32>>;
    fn ok(&self) -> bool;
}

// 拦截器
#[allow(dead_code)]
pub fn interceptor<A: Auth>(a: A) -> Option<Response<Vec<i32>>> {
    if !a.ok() {
        return Some(a.response())
    }
    None
}