1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101

use hyper::server::Handler;
use hyper::server::Server as HttpServer;
use hyper::server::Request as HttpRequest;
use hyper::server::Response as HttpResponse;
use router::Router;
use public::Public;
use context::Context;
use middleware::Middleware;
use view::View;
use mage::Cache;
use response::Response;
use request::Request;


/// Web application.
pub struct Application {
    /// Router.
    pub router: Router,
    /// DynamicContext for template engine.
    pub context: Context,
    /// Middleware.
    pub middleware: Middleware,
    /// Public directory.
    pub public: Public,
    /// View setting.
    pub view: View,

    cache: Cache,
}

impl Application {
    /// Create a web application.
    pub fn new() -> Application {
        Default::default()
    }

    /// Start application.
    pub fn listen(mut self, ip: &str, port: usize) {
        self.cache.load(self.view.get_root(), self.view.get_extension());

        match HttpServer::http(format!("{}:{}", ip, port).as_str()) {
            Ok(server) => {
                match server.handle(self) {
                    Ok(listening) => {
                        info!("server has started at: {}", listening.socket);
                    }
                    Err(err) => panic!("{}", err),
                }
            }
            Err(err) => {
                panic!("{}", err);
            }
        }
    }
}

impl Default for Application {
    fn default() -> Self {
        Application {
            router: Router::new(),
            context: Context::new(),
            middleware: Middleware::new(),
            public: Public::new(),
            view: View::new(),
            cache: Cache::new(),
        }
    }
}

impl Handler for Application {
    fn handle<'a>(&'a self, http_req: HttpRequest, http_res: HttpResponse<'a>) {
        let res = Response::new(http_res,
                                http_req.headers.clone(),
                                &self.context,
                                &self.view,
                                self.context.get_functions(),
                                &self.cache);
        let mut req = Request::new(http_req);

        match self.router.find(&mut req) {
            Some(handle) => {
                let option = self.middleware.execute_befores(req, res);
                if option.is_some() {
                    let (req, res) = option.unwrap();
                    handle(req, res);
                }
                self.middleware.execute_afters();
            }
            None => {
                match self.public.find(&req.url) {
                    Some(static_file) => res.send_static_file(static_file),
                    None => res.send_error_page(404),
                }
            }
        }
    }
}

unsafe impl Send for Application {}
unsafe impl Sync for Application {}