novel 0.4.2

my web framework.
Documentation
// #[macro_use]
// extern crate lazy_static;

use std::collections::HashMap;
use std::borrow::Cow;
use crate::error::Error;
use std::error::Error as StdError;
use crate::http::form::Error as FormError;
// use std::sync::Arc;
use crate::state::State;
use crate::http::{headers, Request, form::FormData, Response, BodyWriter, StatusCode};
use cookie::{Cookie, CookieJar};
use serde_json;
use serde_urlencoded;
use serde::de::DeserializeOwned;
use std::fs::File;
use std::path::Path;
use url::form_urlencoded;
use std::convert::TryInto;
use futures::{Future, Stream, Async};
use hyper;
use hyper::body::Payload;
use std::sync::Arc;
use std::cell::Ref;
use std::io::prelude::*;
use super::server::ServerConfig;
// type GenericError = Box<dyn std::error::Error + Send + Sync>;
// lazy_static! {
//     static ref HTTP_ERROR_CONTENTS: HashMap<u16, &'static str> = {
//         let mut m = HashMap::new();

//         m
//     };
// }

pub struct Context{
    pub(crate) request: Request,
    pub(crate) response: Response,
    pub(crate) params: HashMap<String, String>,
    pub(crate) server_config: Arc<ServerConfig>,
    pub(crate) state: State,
    pub(crate) cookies: CookieJar,
    is_commited: bool,
}


impl Context{
    pub fn new(server_config: Arc<ServerConfig>, request:Request, response: Response)->Context{
        Context{
            params: HashMap::new(),
            server_config,
            request,
            response,
            state: State::new(),
            is_commited: false,
            cookies: CookieJar::new(),
        }
    }
    pub fn request(&self)->&Request{
        &self.request
    }
    pub fn response(&mut self)->&Response{
        &self.response
    }
    pub fn response_mut(&mut self)->&mut Response{
        &mut self.response
    }

    pub fn params(&self)->&HashMap<String, String>{
        &self.params
    }
    pub fn get_param<T>(&self, key:T) -> Option<&String> where T: AsRef<str> {
        self.params().get(key.as_ref())
    }
    
    #[inline]
    pub fn queries(&self)->&HashMap<String, String>{
        self.request.queries()
    }
    #[inline]
    pub fn get_query<T>(&self, key:T) -> Option<String> where T: AsRef<str> {
        // if let Some(value) = self.request.queries().get(key.as_ref()) {
        //     Some(value.clone())
        // }else{
        //     None
        // }
        self.request.queries().get(key.as_ref()).map(|s|s.clone())
    }
    #[inline]
    pub fn posts(&self) -> &Result<FormData, FormError> {
        self.request.form_data()
    }
    #[inline]
    pub fn get_post<T>(&self, key:T) -> Option<String> where T: AsRef<str> {
        self.request.form_data().as_ref().ok().and_then(|ps|ps.get_one_field(key.as_ref()).map(|s|s.clone()))
    }
    pub fn get_form<T>(&self, key:T) -> Option<String> where T: AsRef<str> {
        self.get_post(key.as_ref()).or(self.get_query(key.as_ref()).map(|s|s.clone()))
    }
    pub fn get_payload(&self) -> Result<String, Error> {
        if let Ok(data) = self.request.body_data().as_ref(){
            match String::from_utf8(data.to_vec()){
                Ok(payload) => Ok(payload),
                Err(err) => Err(Error::Utf8(err)),
            }
        } else {
            Err(Error::General("utf8 encode error".to_owned()))
        }
    }

    pub fn get_cookie<T>(&self, name:T) -> Option<&Cookie<'static>>
        where T: AsRef<str> {
         self.request.cookies().get(name.as_ref())
    }
    pub fn add_cookie(&mut self, cookie: Cookie<'static>) {
        self.cookies.add(cookie);
    }
    pub fn remove_cookie<T>(&mut self, name: T) where T: Into<Cow<'static, str>> {
        self.cookies.remove(Cookie::named(name));
    }
    pub fn state(&self)->&State {
        &self.state
    }
    pub fn state_mut(&mut self)->&mut State {
        &mut self.state
    }

    // pub fn read_from_json<T>(&mut self) -> Result<T, String> where T: DeserializeOwned {
    //     self.get_payload().and_then(|body|serde_json::from_str::<T>(body).map_err(|_|String::from("parse body error")))
    // }
    // pub fn read_from_form<T>(&mut self) -> Result<T, String> where T: DeserializeOwned {
    //     self.get_payload().and_then(|body|serde_urlencoded::from_str::<T>(body).map_err(|_|String::from("parse body error")))
    // }
    // pub fn read<T>(&mut self) -> Result<T, String> where T: DeserializeOwned  {
    //     match self.request.headers().get("content-type") {
    //         Some(ctype) if ctype == "application/x-www-form-urlencoded" => self.read_from_json(),
    //         Some(ctype) if ctype == "application/json" => self.read_from_form(),
    //         _=> Err(String::from("failed to read data"))
    //     }
    // }

    // pub fn render_content(&mut self, content: impl Content){
    //     let (media_type, body_writer) = content.take();
    //     self.render(media_type.to_string(), body_writer);
    // }

    pub fn render_json<T:Into<String>>(&mut self, writer: T) {
        self.render("application/json", writer.into());
    }
    pub fn render_html<T:Into<String>>(&mut self, writer: T) {
        self.render("text/html", writer.into());
    }
    pub fn render_text<T:Into<String>>(&mut self, writer: T) {
        self.render("text/plain", writer.into());
    }
    pub fn render_xml<T:Into<String>>(&mut self, writer: T) {
        self.render("text/xml", writer.into());
    }
    // RenderBinary is like RenderFile() except that it instead of a file on disk,
// it renders store from memory (which could be a file that has not been written,
// the output from some function, or bytes streamed from somewhere else, as long
// it implements io.Reader).  When called directly on something generated or
// streamed, modtime should mostly likely be time.Now().
    pub fn render_binary(&mut self, writer: impl BodyWriter+'static) {
        self.render("text/xml", writer);
    }
    pub fn render_file<T>(&mut self, content_type:T, file: &mut File)->std::io::Result<()> where T: AsRef<str> {
        let mut data = Vec::new();  
        file.read_to_end(&mut data)?;
        self.render(content_type, data);
        Ok(())
    }
    pub fn render_file_from_path<T:AsRef<Path>>(&mut self, path: T)->std::io::Result<()> {
        let mut file = File::open(path.as_ref())?;
        let guess = mime_guess::from_path(path.as_ref());
        return self.render_file(guess.first_or_text_plain().to_string(), &mut file);
    }
    pub fn render<T>(&mut self, content_type:T, writer: impl BodyWriter+'static) where T: AsRef<str> {
        self.response.headers.insert("content-type", content_type.as_ref().parse().unwrap());
        self.write_body(writer);
    }
    pub fn send_file(&mut self, file: File) {
    }
    pub fn send_file_from_path<T>(&mut self, writer: T) where T: AsRef<str> {
    }
    
    pub fn redirect_temporary<U: AsRef<str>>(&mut self, url: U) {
        self.response.status = Some(StatusCode::MOVED_PERMANENTLY);
        self.response.headers.insert(headers::LOCATION, url.as_ref().parse().unwrap());
    }
    pub fn redirect_found<U: AsRef<str>>(&mut self, url: U) {
        self.response.status = Some(StatusCode::FOUND);
        self.response.headers.insert(headers::LOCATION, url.as_ref().parse().unwrap());
    }
    pub fn redirect_other<U: AsRef<str>>(&mut self, url: U) {
        self.response.status = Some(StatusCode::SEE_OTHER);
        self.response.headers.insert(headers::LOCATION, url.as_ref().parse().unwrap());
    }
    // pub fn render_binary(&mut self, writer: impl BodyWriter+'static) {
    //     self.write_body(writer)
    // }
    pub fn write_body(&mut self, writer: impl BodyWriter+'static) {
        self.response.body_writers.push(Box::new(writer))
    }
    pub fn commit(&mut self) {
        self.is_commited = true;
    }
    pub fn is_commited(&self) -> bool{
        self.is_commited
    }

    pub fn not_found(&mut self) {
        self.response.status = Some(StatusCode::NOT_FOUND);
        self.commit();
    }

    pub fn unauthorized(&mut self) {
        self.response.status = Some(StatusCode::UNAUTHORIZED);
        self.commit();
    }

    pub fn forbidden(&mut self) {
        self.response.status = Some(StatusCode::FORBIDDEN);
        self.commit();
    }
}