serv4rs 0.1.7

serv4rs is a powerful, pragmatic, and extremely fast web framework for Rust
Documentation
use std::env;
use std::sync::{Arc, RwLock};

use actix_web::{HttpRequest, HttpResponse};
use serde::Serialize;
use tera::{Context, Tera};

use crate::error::Error;

/// A trait for making certain types of response handling easier.
pub trait Render {
    /// Shorthand for rendering a template, with a specific HTTP response code.
    fn render(&self, code: usize, template: &str, context: Context) -> std::result::Result<HttpResponse, Error>;

    /// Shorthand for returning a JSON payload.
    fn json<S: Serialize>(&self, code: usize, payload: S) -> std::result::Result<HttpResponse, Error>;

    /// Shorthand for returning a text/plain payload.
    fn text<S: Serialize>(&self, code: usize, payload: S) -> std::result::Result<HttpResponse, Error>;

    /// Handy redirects helper.
    fn redirect(&self, location: &str) -> std::result::Result<HttpResponse, Error>;
}

impl Render for HttpRequest {
    fn render(
        &self,
        code: usize,
        template: &str,
        mut context: Context,
    ) -> std::result::Result<HttpResponse, Error> {

        let data: Option<&Arc<RwLock<Tera>>> = self.app_data();

        for (k, v) in env::vars() {
            if k.starts_with("JELLY_") {
                context.insert(&k, &v);
            }
        }

        if let Some(eng) = data {
            let engine = eng.read().map_err(|e| {
                Error::Generic(format!("Error acquiring template read lock: {:?}", e))
            })?;

            let body = engine.render(template, &context).map_err(Error::from)?;

            Ok(match code {
                200 => HttpResponse::Ok(),
                400 => HttpResponse::BadRequest(),
                404 => HttpResponse::NotFound(),
                _ => HttpResponse::Ok(),
            }
            .content_type("text/html; charset=utf-8")
            .body(body))
        } else {
            Err(Error::Generic(
                "Unable to locate Templates cache".to_string(),
            ))
        }
    }

    fn json<S: Serialize>(&self, code: usize, payload: S) -> std::result::Result<HttpResponse, Error> {
        let o = serde_json::to_string(&payload)?;

        Ok(match code {
            200 => HttpResponse::Ok(),
            400 => HttpResponse::BadRequest(),
            404 => HttpResponse::NotFound(),
            _ => HttpResponse::Ok(),
        }
        .content_type("application/json")
        .body(o))
    }

    fn text<S: Serialize>(&self, code: usize, payload: S) -> std::result::Result<HttpResponse, Error> {
        let o = serde_json::to_string(&payload)?;

        Ok(match code {
            200 => HttpResponse::Ok(),
            400 => HttpResponse::BadRequest(),
            404 => HttpResponse::NotFound(),
            _ => HttpResponse::Ok(),
        }
        .content_type("text/plain")
        .body(o))
    }

    fn redirect(&self, location: &str) -> std::result::Result<HttpResponse, Error> {
        Ok(HttpResponse::Found()
            .append_header((actix_web::http::header::LOCATION, location))
            .finish())
    }

}