diff --git a/examples/basic.rs b/examples/basic.rs
index bf740dc23..c83d9b329 100644
--- a/examples/basic.rs
+++ b/examples/basic.rs
@@ -1,4 +1,6 @@
 #![allow(unused_variables)]
+#![cfg_attr(feature="cargo-clippy", allow(needless_pass_by_value))]
+
 extern crate actix;
 extern crate actix_web;
 extern crate env_logger;
@@ -6,17 +8,27 @@ extern crate futures;
 
 use actix_web::*;
 use actix_web::error::Result;
+use actix_web::middlewares::RequestSession;
 use futures::stream::{once, Once};
 
 /// somple handle
-fn index(req: &mut HttpRequest, mut _payload: Payload, state: &()) -> HttpResponse {
+fn index(req: &mut HttpRequest, mut _payload: Payload, state: &()) -> Result<HttpResponse> {
     println!("{:?}", req);
     if let Ok(ch) = _payload.readany() {
         if let futures::Async::Ready(Some(d)) = ch {
             println!("{}", String::from_utf8_lossy(d.0.as_ref()));
         }
     }
-    httpcodes::HTTPOk.into()
+
+    // session
+    if let Some(count) = req.session().get::<i32>("counter")? {
+        println!("SESSION value: {}", count);
+        req.session().set("counter", count+1)?;
+    } else {
+        req.session().set("counter", 1)?;
+    }
+
+    Ok(httpcodes::HTTPOk.into())
 }
 
 /// somple handle
@@ -51,6 +63,12 @@ fn main() {
         Application::default("/")
             // enable logger
             .middleware(middlewares::Logger::default())
+            // cookie session middleware
+            .middleware(middlewares::SessionStorage::new(
+                middlewares::CookieSessionBackend::build(&[0; 32])
+                    .secure(false)
+                    .finish()
+            ))
             // register simple handle r, handle all methods
             .handler("/index.html", index)
             // with path parameters
diff --git a/examples/state.rs b/examples/state.rs
index 3b7bba380..7844288a1 100644
--- a/examples/state.rs
+++ b/examples/state.rs
@@ -72,7 +72,7 @@ fn main() {
     let sys = actix::System::new("ws-example");
 
     HttpServer::new(
-        Application::builder("/", AppState{counter: Cell::new(0)})
+        Application::build("/", AppState{counter: Cell::new(0)})
             // enable logger
             .middleware(middlewares::Logger::default())
             // websocket route
diff --git a/src/application.rs b/src/application.rs
index 6c64e2307..b6cf27a88 100644
--- a/src/application.rs
+++ b/src/application.rs
@@ -1,5 +1,4 @@
 use std::rc::Rc;
-use std::string::ToString;
 use std::collections::HashMap;
 
 use task::Task;
@@ -58,11 +57,11 @@ impl<S: 'static> HttpHandler for Application<S> {
 impl Application<()> {
 
     /// Create default `ApplicationBuilder` with no state
-    pub fn default<T: ToString>(prefix: T) -> ApplicationBuilder<()> {
+    pub fn default<T: Into<String>>(prefix: T) -> ApplicationBuilder<()> {
         ApplicationBuilder {
             parts: Some(ApplicationBuilderParts {
                 state: (),
-                prefix: prefix.to_string(),
+                prefix: prefix.into(),
                 default: Resource::default_not_found(),
                 handlers: HashMap::new(),
                 resources: HashMap::new(),
@@ -77,11 +76,11 @@ impl<S> Application<S> where S: 'static {
     /// Create application builder with specific state. State is shared with all
     /// routes within same application and could be
     /// accessed with `HttpContext::state()` method.
-    pub fn builder<T: ToString>(prefix: T, state: S) -> ApplicationBuilder<S> {
+    pub fn build<T: Into<String>>(prefix: T, state: S) -> ApplicationBuilder<S> {
         ApplicationBuilder {
             parts: Some(ApplicationBuilderParts {
                 state: state,
-                prefix: prefix.to_string(),
+                prefix: prefix.into(),
                 default: Resource::default_not_found(),
                 handlers: HashMap::new(),
                 resources: HashMap::new(),
@@ -100,7 +99,7 @@ struct ApplicationBuilderParts<S> {
     middlewares: Vec<Box<Middleware>>,
 }
 
-/// Application builder
+/// Structure that follows the builder pattern for building `Application` structs.
 pub struct ApplicationBuilder<S=()> {
     parts: Option<ApplicationBuilderParts<S>>,
 }
@@ -158,14 +157,14 @@ impl<S> ApplicationBuilder<S> where S: 'static {
     ///         .finish();
     /// }
     /// ```
-    pub fn resource<F, P: ToString>(&mut self, path: P, f: F) -> &mut Self
+    pub fn resource<F, P: Into<String>>(&mut self, path: P, f: F) -> &mut Self
         where F: FnOnce(&mut Resource<S>) + 'static
     {
         {
             let parts = self.parts.as_mut().expect("Use after finish");
 
             // add resource
-            let path = path.to_string();
+            let path = path.into();
             if !parts.resources.contains_key(&path) {
                 check_pattern(&path);
                 parts.resources.insert(path.clone(), Resource::default());
@@ -208,21 +207,21 @@ impl<S> ApplicationBuilder<S> where S: 'static {
     pub fn handler<P, F, R>(&mut self, path: P, handler: F) -> &mut Self
         where F: Fn(&mut HttpRequest, Payload, &S) -> R + 'static,
               R: Into<HttpResponse> + 'static,
-              P: ToString,
+              P: Into<String>,
     {
         self.parts.as_mut().expect("Use after finish")
-            .handlers.insert(path.to_string(), Box::new(FnHandler::new(handler)));
+            .handlers.insert(path.into(), Box::new(FnHandler::new(handler)));
         self
     }
 
     /// Add path handler
     pub fn route_handler<H, P>(&mut self, path: P, h: H) -> &mut Self
-        where H: RouteHandler<S> + 'static, P: ToString
+        where H: RouteHandler<S> + 'static, P: Into<String>
     {
         {
             // add resource
             let parts = self.parts.as_mut().expect("Use after finish");
-            let path = path.to_string();
+            let path = path.into();
             if parts.handlers.contains_key(&path) {
                 panic!("Handler already registered: {:?}", path);
             }
diff --git a/src/encoding.rs b/src/encoding.rs
index 27138ff73..7bdbaea49 100644
--- a/src/encoding.rs
+++ b/src/encoding.rs
@@ -69,7 +69,7 @@ impl<'a> From<&'a str> for ContentEncoding {
 
 pub(crate) enum PayloadType {
     Sender(PayloadSender),
-    Encoding(EncodedPayload),
+    Encoding(Box<EncodedPayload>),
 }
 
 impl PayloadType {
@@ -89,7 +89,7 @@ impl PayloadType {
         match enc {
             ContentEncoding::Auto | ContentEncoding::Identity =>
                 PayloadType::Sender(sender),
-            _ => PayloadType::Encoding(EncodedPayload::new(sender, enc)),
+            _ => PayloadType::Encoding(Box::new(EncodedPayload::new(sender, enc))),
         }
     }
 }
diff --git a/src/error.rs b/src/error.rs
index ea977505d..f3b1507d2 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -29,7 +29,7 @@ use httpcodes::{HTTPBadRequest, HTTPMethodNotAllowed, HTTPExpectationFailed};
 /// is otherwise a direct mapping to `Result`.
 pub type Result<T> = result::Result<T, Error>;
 
-/// Actix web error
+/// General purpose actix web error
 #[derive(Debug)]
 pub struct Error {
     cause: Box<ErrorResponse>,
diff --git a/src/h1.rs b/src/h1.rs
index 6fdb5ea7c..39f5e6afe 100644
--- a/src/h1.rs
+++ b/src/h1.rs
@@ -51,7 +51,6 @@ pub(crate) struct Http1<T: AsyncWrite + 'static, H: 'static> {
 
 struct Entry {
     task: Pipeline,
-    //req: UnsafeCell<HttpRequest>,
     eof: bool,
     error: bool,
     finished: bool,
@@ -105,7 +104,6 @@ impl<T, H> Http1<T, H>
                         return Err(())
                     }
 
-                    // this is anoying
                     match item.task.poll_io(&mut self.stream) {
                         Ok(Async::Ready(ready)) => {
                             not_ready = false;
diff --git a/src/h2.rs b/src/h2.rs
index 95fd6d65c..572843b8c 100644
--- a/src/h2.rs
+++ b/src/h2.rs
@@ -82,7 +82,6 @@ impl<T, H> Http2<T, H>
                     item.poll_payload();
 
                     if !item.eof {
-                        //let req = unsafe {item.req.get().as_mut().unwrap()};
                         match item.task.poll_io(&mut item.stream) {
                             Ok(Async::Ready(ready)) => {
                                 item.eof = true;
diff --git a/src/httprequest.rs b/src/httprequest.rs
index 4f3caaa1e..bde2e34d0 100644
--- a/src/httprequest.rs
+++ b/src/httprequest.rs
@@ -141,7 +141,7 @@ impl HttpRequest {
     }
 
     /// Load cookies
-    pub fn load_cookies(&mut self) -> Result<&Vec<Cookie>, CookieParseError>
+    pub fn load_cookies(&mut self) -> Result<&Vec<Cookie<'static>>, CookieParseError>
     {
         if !self.cookies_loaded {
             self.cookies_loaded = true;
diff --git a/src/middlewares/mod.rs b/src/middlewares/mod.rs
index 6699edab6..66913fa45 100644
--- a/src/middlewares/mod.rs
+++ b/src/middlewares/mod.rs
@@ -8,8 +8,8 @@ use httpresponse::HttpResponse;
 mod logger;
 mod session;
 pub use self::logger::Logger;
-pub use self::session::{RequestSession, Session, SessionImpl,
-                        SessionBackend, SessionStorage, CookieSessionBackend};
+pub use self::session::{RequestSession, Session, SessionImpl, SessionBackend, SessionStorage,
+                        CookieSessionError, CookieSessionBackend, CookieSessionBackendBuilder};
 
 /// Middleware start result
 pub enum Started {
diff --git a/src/middlewares/session.rs b/src/middlewares/session.rs
index 79f70804e..c89817f91 100644
--- a/src/middlewares/session.rs
+++ b/src/middlewares/session.rs
@@ -3,7 +3,10 @@
 use std::any::Any;
 use std::rc::Rc;
 use std::sync::Arc;
+use std::collections::HashMap;
+
 use serde_json;
+use serde_json::error::Error as JsonError;
 use serde::{Serialize, Deserialize};
 use http::header::{self, HeaderValue};
 use cookie::{CookieJar, Cookie, Key};
@@ -157,63 +160,160 @@ impl SessionImpl for DummySessionImpl {
 
 /// Session that uses signed cookies as session storage
 pub struct CookieSession {
-    jar: CookieJar,
-    key: Rc<Key>,
+    changed: bool,
+    state: HashMap<String, String>,
+    inner: Rc<CookieSessionInner>,
 }
 
+/// Errors that can occure during handling cookie session
+#[derive(Fail, Debug)]
+pub enum CookieSessionError {
+    /// Size of the serialized session is greater than 4000 bytes.
+    #[fail(display="Size of the serialized session is greater than 4000 bytes.")]
+    Overflow,
+    /// Fail to serialize session.
+    #[fail(display="Fail to serialize session")]
+    Serialize(JsonError),
+}
+
+impl ErrorResponse for CookieSessionError {}
+
 impl SessionImpl for CookieSession {
 
     fn get(&self, key: &str) -> Option<&str> {
-        unimplemented!()
-    }
-
-    fn set(&mut self, key: &str, value: String) {
-        unimplemented!()
-    }
-
-    fn remove(&mut self, key: &str) {
-        unimplemented!()
-    }
-
-    fn clear(&mut self) {
-        let cookies: Vec<_> = self.jar.iter().cloned().collect();
-        for cookie in cookies {
-            self.jar.remove(cookie);
+        if let Some(s) = self.state.get(key) {
+            Some(s)
+        } else {
+            None
         }
     }
 
+    fn set(&mut self, key: &str, value: String) {
+        self.changed = true;
+        self.state.insert(key.to_owned(), value);
+    }
+
+    fn remove(&mut self, key: &str) {
+        self.changed = true;
+        self.state.remove(key);
+    }
+
+    fn clear(&mut self) {
+        self.changed = true;
+        self.state.clear()
+    }
+
     fn write(&self, mut resp: HttpResponse) -> Response {
-        for cookie in self.jar.delta() {
-            match HeaderValue::from_str(&cookie.to_string()) {
-                Err(err) => return Response::Err(err.into()),
-                Ok(val) => resp.headers.append(header::SET_COOKIE, val),
-            };
+        if self.changed {
+            let _ = self.inner.set_cookie(&mut resp, &self.state);
         }
         Response::Done(resp)
     }
 }
 
+struct CookieSessionInner {
+    key: Key,
+    name: String,
+    path: String,
+    domain: Option<String>,
+    secure: bool,
+    http_only: bool,
+}
+
+impl CookieSessionInner {
+
+    fn new(key: &[u8]) -> CookieSessionInner {
+        CookieSessionInner {
+            key: Key::from_master(key),
+            name: "actix_session".to_owned(),
+            path: "/".to_owned(),
+            domain: None,
+            secure: true,
+            http_only: true }
+    }
+
+    fn set_cookie(&self, resp: &mut HttpResponse, state: &HashMap<String, String>) -> Result<()> {
+        let value = serde_json::to_string(&state)
+            .map_err(CookieSessionError::Serialize)?;
+        if value.len() > 4064 {
+            return Err(CookieSessionError::Overflow.into())
+        }
+
+        let mut cookie = Cookie::new(self.name.clone(), value);
+        cookie.set_path(self.path.clone());
+        cookie.set_secure(self.secure);
+        cookie.set_http_only(self.http_only);
+
+        if let Some(ref domain) = self.domain {
+            cookie.set_domain(domain.clone());
+        }
+
+        let mut jar = CookieJar::new();
+        jar.signed(&self.key).add(cookie);
+
+        for cookie in jar.delta() {
+            let val = HeaderValue::from_str(&cookie.to_string())?;
+            resp.headers_mut().append(header::SET_COOKIE, val);
+        }
+
+        Ok(())
+    }
+
+    fn load(&self, req: &mut HttpRequest) -> HashMap<String, String> {
+        if let Ok(cookies) = req.load_cookies() {
+            for cookie in cookies {
+                if cookie.name() == self.name {
+                    let mut jar = CookieJar::new();
+                    jar.add_original(cookie.clone());
+                    if let Some(cookie) = jar.signed(&self.key).get(&self.name) {
+                        if let Ok(val) = serde_json::from_str(cookie.value()) {
+                            return val;
+                        }
+                    }
+                }
+            }
+        }
+        HashMap::new()
+    }
+}
+
 /// Use signed cookies as session storage.
 ///
+/// `CookieSessionBackend` creates sessions which are limited to storing
+/// fewer than 4000 bytes of data (as the payload must fit into a single cookie).
+/// Internal server error get generated if session contains more than 4000 bytes.
+///
 /// You need to pass a random value to the constructor of `CookieSessionBackend`.
 /// This is private key for cookie session, When this value is changed, all session data is lost.
 ///
 /// Note that whatever you write into your session is visible by the user (but not modifiable).
 ///
 /// Constructor panics if key length is less than 32 bytes.
-pub struct CookieSessionBackend {
-    key: Rc<Key>,
-}
+pub struct CookieSessionBackend(Rc<CookieSessionInner>);
 
 impl CookieSessionBackend {
 
     /// Construct new `CookieSessionBackend` instance.
     ///
     /// Panics if key length is less than 32 bytes.
-    pub fn new(key: &[u8]) -> Self {
-        CookieSessionBackend {
-            key: Rc::new(Key::from_master(key)),
-        }
+    pub fn new(key: &[u8]) -> CookieSessionBackend {
+        CookieSessionBackend(
+            Rc::new(CookieSessionInner::new(key)))
+    }
+
+    /// Creates a new `CookieSessionBackendBuilder` instance from the given key.
+    ///
+    /// Panics if key length is less than 32 bytes.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use actix_web::middlewares::CookieSessionBackend;
+    ///
+    /// let backend = CookieSessionBackend::build(&[0; 32]).finish();
+    /// ```
+    pub fn build(key: &[u8]) -> CookieSessionBackendBuilder {
+        CookieSessionBackendBuilder::new(key)
     }
 }
 
@@ -223,6 +323,74 @@ impl SessionBackend for CookieSessionBackend {
     type ReadFuture = FutureResult<CookieSession, Error>;
 
     fn from_request(&self, req: &mut HttpRequest) -> Self::ReadFuture {
-        unimplemented!()
+        let state = self.0.load(req);
+        FutOk(
+            CookieSession {
+                changed: false,
+                state: state,
+                inner: Rc::clone(&self.0),
+            })
+    }
+}
+
+/// Structure that follows the builder pattern for building `CookieSessionBackend` structs.
+///
+/// To construct a backend:
+///
+///   1. Call [`CookieSessionBackend::build`](struct.CookieSessionBackend.html#method.build) to start building.
+///   2. Use any of the builder methods to set fields in the backend.
+///   3. Call [finish](#method.finish) to retrieve the constructed backend.
+///
+/// # Example
+///
+/// ```rust
+/// # extern crate actix_web;
+///
+/// use actix_web::middlewares::CookieSessionBackend;
+///
+/// # fn main() {
+/// let backend: CookieSessionBackend = CookieSessionBackend::build(&[0; 32])
+///     .domain("www.rust-lang.org")
+///     .path("/")
+///     .secure(true)
+///     .http_only(true)
+///     .finish();
+/// # }
+/// ```
+pub struct CookieSessionBackendBuilder(CookieSessionInner);
+
+impl CookieSessionBackendBuilder {
+    pub fn new(key: &[u8]) -> CookieSessionBackendBuilder {
+        CookieSessionBackendBuilder(
+            CookieSessionInner::new(key))
+    }
+
+    /// Sets the `path` field in the session cookie being built.
+    pub fn path<S: Into<String>>(mut self, value: S) -> CookieSessionBackendBuilder {
+        self.0.path = value.into();
+        self
+    }
+
+    /// Sets the `domain` field in the session cookie being built.
+    pub fn domain<S: Into<String>>(mut self, value: S) -> CookieSessionBackendBuilder {
+        self.0.domain = Some(value.into());
+        self
+    }
+
+    /// Sets the `secure` field in the session cookie being built.
+    pub fn secure(mut self, value: bool) -> CookieSessionBackendBuilder {
+        self.0.secure = value;
+        self
+    }
+
+    /// Sets the `http_only` field in the session cookie being built.
+    pub fn http_only(mut self, value: bool) -> CookieSessionBackendBuilder {
+        self.0.http_only = value;
+        self
+    }
+
+    /// Finishes building and returns the built `CookieSessionBackend`.
+    pub fn finish(self) -> CookieSessionBackend {
+        CookieSessionBackend(Rc::new(self.0))
     }
 }
diff --git a/src/pipeline.rs b/src/pipeline.rs
index aa9979910..d6bc5fff4 100644
--- a/src/pipeline.rs
+++ b/src/pipeline.rs
@@ -55,9 +55,7 @@ impl Pipeline {
                 st.disconnected(),
             PipelineState::Handle(ref mut st) =>
                 st.task.disconnected(),
-            PipelineState::Task(ref mut st) =>
-                st.0.disconnected(),
-            PipelineState::Error(ref mut st) =>
+            PipelineState::Task(ref mut st) | PipelineState::Error(ref mut st) =>
                 st.0.disconnected(),
             _ =>(),
         }
diff --git a/src/recognizer.rs b/src/recognizer.rs
index 71acfd4ac..480e5a89a 100644
--- a/src/recognizer.rs
+++ b/src/recognizer.rs
@@ -1,5 +1,4 @@
 use std::rc::Rc;
-use std::string::ToString;
 use std::collections::HashMap;
 
 use regex::{Regex, RegexSet, Captures};
@@ -25,7 +24,7 @@ impl<T> Default for RouteRecognizer<T> {
 
 impl<T> RouteRecognizer<T> {
 
-    pub fn new<P: ToString, U>(prefix: P, routes: U) -> Self
+    pub fn new<P: Into<String>, U>(prefix: P, routes: U) -> Self
         where U: IntoIterator<Item=(String, T)>
     {
         let mut paths = Vec::new();
@@ -38,7 +37,7 @@ impl<T> RouteRecognizer<T> {
         let regset = RegexSet::new(&paths);
 
         RouteRecognizer {
-            prefix: prefix.to_string().len() - 1,
+            prefix: prefix.into().len() - 1,
             patterns: regset.unwrap(),
             routes: handlers,
         }
@@ -56,8 +55,8 @@ impl<T> RouteRecognizer<T> {
         self.routes = handlers;
     }
 
-    pub fn set_prefix<P: ToString>(&mut self, prefix: P) {
-        let p = prefix.to_string();
+    pub fn set_prefix<P: Into<String>>(&mut self, prefix: P) {
+        let p = prefix.into();
         if p.ends_with('/') {
             self.prefix = p.len() - 1;
         } else {
@@ -105,7 +104,7 @@ impl Pattern {
             None => return None,
         };
 
-        Some(Params::new(Rc::clone(&self.names), text, captures))
+        Some(Params::new(Rc::clone(&self.names), text, &captures))
     }
 }
 
@@ -176,7 +175,7 @@ pub struct Params {
 impl Params {
     pub(crate) fn new(names: Rc<HashMap<String, usize>>,
                       text: &str,
-                      captures: Captures) -> Self
+                      captures: &Captures) -> Self
     {
         Params {
             names,
diff --git a/src/resource.rs b/src/resource.rs
index 3e1341501..ceeba4707 100644
--- a/src/resource.rs
+++ b/src/resource.rs
@@ -1,5 +1,4 @@
 use std::rc::Rc;
-use std::convert::From;
 use std::marker::PhantomData;
 use std::collections::HashMap;
 
@@ -60,8 +59,8 @@ impl<S> Resource<S> where S: 'static {
     }
 
     /// Set resource name
-    pub fn set_name<T: ToString>(&mut self, name: T) {
-        self.name = name.to_string();
+    pub fn set_name<T: Into<String>>(&mut self, name: T) {
+        self.name = name.into();
     }
 
     /// Register handler for specified method.
@@ -136,7 +135,6 @@ impl<S: 'static> RouteHandler<S> for Resource<S> {
     }
 }
 
-
 #[cfg_attr(feature="cargo-clippy", allow(large_enum_variant))]
 enum ReplyItem<A> where A: Actor + Route {
     Message(HttpResponse),
diff --git a/src/staticfiles.rs b/src/staticfiles.rs
index b7e1a80ab..00222fed7 100644
--- a/src/staticfiles.rs
+++ b/src/staticfiles.rs
@@ -72,7 +72,7 @@ impl StaticFiles {
         }
     }
 
-    fn index(&self, relpath: &str, filename: PathBuf) -> Result<HttpResponse, io::Error> {
+    fn index(&self, relpath: &str, filename: &PathBuf) -> Result<HttpResponse, io::Error> {
         let index_of = format!("Index of {}/{}", self.prefix, relpath);
         let mut body = String::new();
 
@@ -169,7 +169,7 @@ impl<S: 'static> RouteHandler<S> for StaticFiles {
             };
 
             if filename.is_dir() {
-                match self.index(&filepath[idx..], filename) {
+                match self.index(&filepath[idx..], &filename) {
                     Ok(resp) => Task::reply(resp),
                     Err(err) => match err.kind() {
                         io::ErrorKind::NotFound => Task::reply(HTTPNotFound),