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
102
103
104
105
106
107
108
//! The `zap` web framework crate.
//!
//! ## Example
//!
//! Here a short HelloWorld example writte in Rust with zap:
//!
//! ```no_run
//! extern crate zap;
//!
//! use std::io::Error as ZapError;
//! use zap::prelude::*;
//!
//! struct HelloWorld;
//!
//! impl Handler for HelloWorld {
//!     type Request = Request;
//!     type Response = Response;
//!     type Error = ZapError;
//!     type Future = ZapResult;
//!
//!     fn call(&self, _ : Request) -> ZapResult {
//!         let mut resp = Response::new();
//!
//!         resp.body("Hello World!");
//!
//!         resp.ok()
//!     }
//! }
//! ```
//!

// Load all crates and modules
extern crate bytes;
extern crate futures;
extern crate tokio_io;
extern crate tokio_proto;
extern crate tokio_service;

mod request;
mod response;

// Use the stuff we need to
use std::io;

use bytes::BytesMut;
use tokio_io::codec::{Encoder, Decoder, Framed};
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_proto::pipeline::ServerProto;
use futures::future;

// Make Server, Handler, Request and Response public accessable
pub use tokio_proto::TcpServer as Server;
pub use tokio_service::Service as Handler;
pub use request::Request;
pub use response::Response;

/// The expected response result
pub type ZapResult = future::Ok<Response, io::Error>;

/// A module to import the required things.
pub mod prelude {
    pub use ZapResult;
    pub use Server;
    pub use Handler;
    pub use request::Request;
    pub use response::Response;
    pub use Http;
}

/// Handling incoming requests with tokio-proto
pub struct Http;

impl<T: AsyncRead + AsyncWrite + 'static> ServerProto<T> for Http {
    // Setup ServerProto types
    type Request = Request;
    type Response = Response;
    type Transport = Framed<T, HttpCodec>;
    type BindTransport = io::Result<Framed<T, HttpCodec>>;

    fn bind_transport(&self, io: T) -> io::Result<Framed<T, HttpCodec>> {
        // Frame the request with tokio-io and handle it with HttpCodec
        Ok(io.framed(HttpCodec))
    }
}

/// Encode and decode our request
pub struct HttpCodec;

impl Decoder for HttpCodec {
    type Item = Request;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<Request>> {
        // Decode our buffer
        request::decode(buf)
    }
}

impl Encoder for HttpCodec {
    type Item = Response;
    type Error = io::Error;

    fn encode(&mut self, msg: Response, buf: &mut BytesMut) -> io::Result<()> {
        // Encode and write response
        response::encode(&msg, buf);
        Ok(())
    }
}