From 8e0a7f44d411bf10243899c3d4dc449c5a02a30e Mon Sep 17 00:00:00 2001
From: Nikolay Kim <fafhrd91@gmail.com>
Date: Sun, 26 Nov 2017 20:32:12 -0800
Subject: [PATCH] pass request by value

---
 README.md             |   6 +-
 examples/basic.rs     |   6 +-
 examples/state.rs     |   8 +--
 examples/websocket.rs |   6 +-
 src/application.rs    |   9 ++-
 src/httpcodes.rs      |   2 +-
 src/httprequest.rs    | 152 ++++++++++++++++++++++++------------------
 src/pipeline.rs       |  14 ++--
 src/resource.rs       |   6 +-
 src/route.rs          |  26 ++++----
 src/staticfiles.rs    |   2 +-
 src/ws.rs             |   4 +-
 12 files changed, 132 insertions(+), 109 deletions(-)

diff --git a/README.md b/README.md
index e91c3be3..b4c3773f 100644
--- a/README.md
+++ b/README.md
@@ -83,14 +83,14 @@ impl Actor for MyWebSocket {
 impl Route for MyWebSocket {
     type State = ();
 
-    fn request(req: &mut HttpRequest, ctx: &mut HttpContext<Self>) -> RouteResult<Self>
+    fn request(mut req: HttpRequest, ctx: &mut HttpContext<Self>) -> RouteResult<Self>
     {
         // websocket handshake
-        let resp = ws::handshake(req)?;
+        let resp = ws::handshake(&req)?;
         // send HttpResponse back to peer
         ctx.start(resp);
         // convert bytes stream to a stream of `ws::Message` and handle stream
-        ctx.add_stream(ws::WsStream::new(req));
+        ctx.add_stream(ws::WsStream::new(&mut req));
         Reply::async(MyWebSocket)
     }
 }
diff --git a/examples/basic.rs b/examples/basic.rs
index b79cd3f3..f9104837 100644
--- a/examples/basic.rs
+++ b/examples/basic.rs
@@ -12,7 +12,7 @@ use actix_web::middlewares::RequestSession;
 use futures::stream::{once, Once};
 
 /// somple handle
-fn index(req: &mut HttpRequest, state: &()) -> Result<HttpResponse> {
+fn index(mut req: HttpRequest, state: &()) -> Result<HttpResponse> {
     println!("{:?}", req);
     if let Ok(ch) = req.payload_mut().readany() {
         if let futures::Async::Ready(Some(d)) = ch {
@@ -32,7 +32,7 @@ fn index(req: &mut HttpRequest, state: &()) -> Result<HttpResponse> {
 }
 
 /// somple handle
-fn index_async(req: &mut HttpRequest, state: &()) -> Once<actix_web::Frame, Error>
+fn index_async(req: HttpRequest, state: &()) -> Once<actix_web::Frame, Error>
 {
     println!("{:?}", req);
 
@@ -44,7 +44,7 @@ fn index_async(req: &mut HttpRequest, state: &()) -> Once<actix_web::Frame, Erro
 }
 
 /// handle with path parameters like `/user/{name}/`
-fn with_param(req: &mut HttpRequest, state: &()) -> Result<HttpResponse>
+fn with_param(req: HttpRequest, state: &()) -> Result<HttpResponse>
 {
     println!("{:?}", req);
 
diff --git a/examples/state.rs b/examples/state.rs
index debd7f78..22550a56 100644
--- a/examples/state.rs
+++ b/examples/state.rs
@@ -15,7 +15,7 @@ struct AppState {
 }
 
 /// somple handle
-fn index(req: &mut HttpRequest, state: &AppState) -> HttpResponse {
+fn index(req: HttpRequest, state: &AppState) -> HttpResponse {
     println!("{:?}", req);
     state.counter.set(state.counter.get() + 1);
     httpcodes::HTTPOk.with_body(
@@ -36,11 +36,11 @@ impl Route for MyWebSocket {
     /// Shared application state
     type State = AppState;
 
-    fn request(req: &mut HttpRequest, ctx: &mut HttpContext<Self>) -> RouteResult<Self>
+    fn request(mut req: HttpRequest, ctx: &mut HttpContext<Self>) -> RouteResult<Self>
     {
-        let resp = ws::handshake(req)?;
+        let resp = ws::handshake(&req)?;
         ctx.start(resp);
-        ctx.add_stream(ws::WsStream::new(req));
+        ctx.add_stream(ws::WsStream::new(&mut req));
         Reply::async(MyWebSocket{counter: 0})
     }
 }
diff --git a/examples/websocket.rs b/examples/websocket.rs
index 70e40cd6..59e363b8 100644
--- a/examples/websocket.rs
+++ b/examples/websocket.rs
@@ -22,14 +22,14 @@ impl Actor for MyWebSocket {
 impl Route for MyWebSocket {
     type State = ();
 
-    fn request(req: &mut HttpRequest, ctx: &mut HttpContext<Self>) -> RouteResult<Self>
+    fn request(mut req: HttpRequest, ctx: &mut HttpContext<Self>) -> RouteResult<Self>
     {
         // websocket handshake
-        let resp = ws::handshake(req)?;
+        let resp = ws::handshake(&req)?;
         // send HttpResponse back to peer
         ctx.start(resp);
         // convert bytes stream to a stream of `ws::Message` and register it
-        ctx.add_stream(ws::WsStream::new(req));
+        ctx.add_stream(ws::WsStream::new(&mut req));
         Reply::async(MyWebSocket)
     }
 }
diff --git a/src/application.rs b/src/application.rs
index 30e976be..399cac8d 100644
--- a/src/application.rs
+++ b/src/application.rs
@@ -24,7 +24,7 @@ pub struct Application<S> {
 
 impl<S: 'static> Application<S> {
 
-    fn run(&self, req: &mut HttpRequest) -> Task {
+    fn run(&self, mut req: HttpRequest) -> Task {
         if let Some((params, h)) = self.router.recognize(req.path()) {
             if let Some(params) = params {
                 req.set_match_info(params);
@@ -48,8 +48,7 @@ impl<S: 'static> HttpHandler for Application<S> {
     }
     
     fn handle(&self, req: HttpRequest) -> Pipeline {
-        Pipeline::new(req, Rc::clone(&self.middlewares),
-                      &|req: &mut HttpRequest| {self.run(req)})
+        Pipeline::new(req, Rc::clone(&self.middlewares), &|req: HttpRequest| {self.run(req)})
     }
 }
 
@@ -139,7 +138,7 @@ impl<S> ApplicationBuilder<S> where S: 'static {
     /// impl Route for MyRoute {
     ///     type State = ();
     ///
-    ///     fn request(req: &mut HttpRequest, ctx: &mut HttpContext<Self>) -> RouteResult<Self> {
+    ///     fn request(req: HttpRequest, ctx: &mut HttpContext<Self>) -> RouteResult<Self> {
     ///         Reply::reply(httpcodes::HTTPOk)
     ///     }
     /// }
@@ -202,7 +201,7 @@ 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, &S) -> R + 'static,
+        where F: Fn(HttpRequest, &S) -> R + 'static,
               R: Into<HttpResponse> + 'static,
               P: Into<String>,
     {
diff --git a/src/httpcodes.rs b/src/httpcodes.rs
index 3e8f5c83..bb5905aa 100644
--- a/src/httpcodes.rs
+++ b/src/httpcodes.rs
@@ -70,7 +70,7 @@ impl StaticResponse {
 }
 
 impl<S> RouteHandler<S> for StaticResponse {
-    fn handle(&self, _: &mut HttpRequest, _: Rc<S>) -> Task {
+    fn handle(&self, _: HttpRequest, _: Rc<S>) -> Task {
         Task::reply(HttpResponse::new(self.0, Body::Empty))
     }
 }
diff --git a/src/httprequest.rs b/src/httprequest.rs
index 8a408694..75db9b93 100644
--- a/src/httprequest.rs
+++ b/src/httprequest.rs
@@ -1,5 +1,6 @@
 //! HTTP Request message related code.
 use std::{str, fmt, mem};
+use std::rc::Rc;
 use std::net::SocketAddr;
 use std::collections::HashMap;
 use bytes::BytesMut;
@@ -13,45 +14,24 @@ use payload::Payload;
 use multipart::Multipart;
 use error::{ParseError, PayloadError, MultipartError, CookieParseError, HttpRangeError};
 
-
-/// An HTTP Request
-pub struct HttpRequest {
+struct HttpMessage {
     version: Version,
     method: Method,
     path: String,
     query: String,
     headers: HeaderMap,
+    extensions: Extensions,
     params: Params,
     cookies: Vec<Cookie<'static>>,
     cookies_loaded: bool,
-    extensions: Extensions,
     addr: Option<SocketAddr>,
     payload: Payload,
 }
 
-impl HttpRequest {
-    /// Construct a new Request.
-    #[inline]
-    pub fn new(method: Method, path: String,
-               version: Version, headers: HeaderMap, query: String, payload: Payload) -> Self
-    {
-        HttpRequest {
-            method: method,
-            path: path,
-            query: query,
-            version: version,
-            headers: headers,
-            params: Params::empty(),
-            cookies: Vec::new(),
-            cookies_loaded: false,
-            extensions: Extensions::new(),
-            addr: None,
-            payload: payload,
-        }
-    }
+impl Default for HttpMessage {
 
-    pub(crate) fn for_error() -> HttpRequest {
-        HttpRequest {
+    fn default() -> HttpMessage {
+        HttpMessage {
             method: Method::GET,
             path: String::new(),
             query: String::new(),
@@ -60,38 +40,75 @@ impl HttpRequest {
             params: Params::empty(),
             cookies: Vec::new(),
             cookies_loaded: false,
-            extensions: Extensions::new(),
             addr: None,
             payload: Payload::empty(),
+            extensions: Extensions::new(),
         }
     }
+}
+
+/// An HTTP Request
+pub struct HttpRequest(Rc<HttpMessage>);
+
+impl HttpRequest {
+    /// Construct a new Request.
+    #[inline]
+    pub fn new(method: Method, path: String, version: Version,
+               headers: HeaderMap, query: String, payload: Payload) -> HttpRequest
+    {
+        HttpRequest(
+            Rc::new(HttpMessage {
+                method: method,
+                path: path,
+                query: query,
+                version: version,
+                headers: headers,
+                params: Params::empty(),
+                cookies: Vec::new(),
+                cookies_loaded: false,
+                addr: None,
+                payload: payload,
+                extensions: Extensions::new(),
+            })
+        )
+    }
+
+    pub(crate) fn for_error() -> HttpRequest {
+        HttpRequest(Rc::new(HttpMessage::default()))
+    }
+
+    fn as_mut(&mut self) -> &mut HttpMessage {
+        let r: &HttpMessage = self.0.as_ref();
+        #[allow(mutable_transmutes)]
+        unsafe{mem::transmute(r)}
+    }
 
     /// Protocol extensions.
     #[inline]
     pub fn extensions(&mut self) -> &mut Extensions {
-        &mut self.extensions
+        &mut self.as_mut().extensions
     }
 
     /// Read the Request method.
     #[inline]
-    pub fn method(&self) -> &Method { &self.method }
+    pub fn method(&self) -> &Method { &self.0.method }
 
     /// Read the Request Version.
     #[inline]
     pub fn version(&self) -> Version {
-        self.version
+        self.0.version
     }
 
     /// Read the Request Headers.
     #[inline]
     pub fn headers(&self) -> &HeaderMap {
-        &self.headers
+        &self.0.headers
     }
 
     /// The target path of this Request.
     #[inline]
     pub fn path(&self) -> &str {
-        &self.path
+        &self.0.path
     }
 
     /// Remote IP of client initiated HTTP request.
@@ -103,18 +120,18 @@ impl HttpRequest {
     /// - peername of opened socket
     #[inline]
     pub fn remote(&self) -> Option<&SocketAddr> {
-        self.addr.as_ref()
+        self.0.addr.as_ref()
     }
 
     pub(crate) fn set_remove_addr(&mut self, addr: Option<SocketAddr>) {
-        self.addr = addr
+        self.as_mut().addr = addr
     }
 
     /// Return a new iterator that yields pairs of `Cow<str>` for query parameters
     #[inline]
     pub fn query(&self) -> HashMap<String, String> {
         let mut q: HashMap<String, String> = HashMap::new();
-        for (key, val) in form_urlencoded::parse(self.query.as_ref()) {
+        for (key, val) in form_urlencoded::parse(self.0.query.as_ref()) {
             q.insert(key.to_string(), val.to_string());
         }
         q
@@ -125,17 +142,17 @@ impl HttpRequest {
     /// E.g., id=10
     #[inline]
     pub fn query_string(&self) -> &str {
-        &self.query
+        &self.0.query
     }
 
     /// Return request cookies.
     pub fn cookies(&self) -> &Vec<Cookie<'static>> {
-        &self.cookies
+        &self.0.cookies
     }
 
     /// Return request cookie.
     pub fn cookie(&self, name: &str) -> Option<&Cookie> {
-        for cookie in &self.cookies {
+        for cookie in &self.0.cookies {
             if cookie.name() == name {
                 return Some(cookie)
             }
@@ -146,17 +163,18 @@ impl HttpRequest {
     /// Load cookies
     pub fn load_cookies(&mut self) -> Result<&Vec<Cookie<'static>>, CookieParseError>
     {
-        if !self.cookies_loaded {
-            self.cookies_loaded = true;
-            if let Some(val) = self.headers.get(header::COOKIE) {
+        if !self.0.cookies_loaded {
+            let msg = self.as_mut();
+            msg.cookies_loaded = true;
+            if let Some(val) = msg.headers.get(header::COOKIE) {
                 let s = str::from_utf8(val.as_bytes())
                     .map_err(CookieParseError::from)?;
                 for cookie in s.split("; ") {
-                    self.cookies.push(Cookie::parse_encoded(cookie)?.into_owned());
+                    msg.cookies.push(Cookie::parse_encoded(cookie)?.into_owned());
                 }
             }
         }
-        Ok(&self.cookies)
+        Ok(&self.0.cookies)
     }
 
     /// Get a reference to the Params object.
@@ -164,34 +182,34 @@ impl HttpRequest {
     /// Route supports glob patterns: * for a single wildcard segment and :param
     /// for matching storing that segment of the request url in the Params object.
     #[inline]
-    pub fn match_info(&self) -> &Params { &self.params }
+    pub fn match_info(&self) -> &Params { &self.0.params }
 
     /// Set request Params.
     pub fn set_match_info(&mut self, params: Params) {
-        self.params = params;
+        self.as_mut().params = params;
     }
 
     /// Checks if a connection should be kept alive.
     pub fn keep_alive(&self) -> bool {
-        if let Some(conn) = self.headers.get(header::CONNECTION) {
+        if let Some(conn) = self.0.headers.get(header::CONNECTION) {
             if let Ok(conn) = conn.to_str() {
-                if self.version == Version::HTTP_10 && conn.contains("keep-alive") {
+                if self.0.version == Version::HTTP_10 && conn.contains("keep-alive") {
                     true
                 } else {
-                    self.version == Version::HTTP_11 &&
+                    self.0.version == Version::HTTP_11 &&
                         !(conn.contains("close") || conn.contains("upgrade"))
                 }
             } else {
                 false
             }
         } else {
-            self.version != Version::HTTP_10
+            self.0.version != Version::HTTP_10
         }
     }
 
     /// Read the request content type
     pub fn content_type(&self) -> &str {
-        if let Some(content_type) = self.headers.get(header::CONTENT_TYPE) {
+        if let Some(content_type) = self.0.headers.get(header::CONTENT_TYPE) {
             if let Ok(content_type) = content_type.to_str() {
                 return content_type
             }
@@ -201,17 +219,17 @@ impl HttpRequest {
 
     /// Check if request requires connection upgrade
     pub(crate) fn upgrade(&self) -> bool {
-        if let Some(conn) = self.headers.get(header::CONNECTION) {
+        if let Some(conn) = self.0.headers.get(header::CONNECTION) {
             if let Ok(s) = conn.to_str() {
                 return s.to_lowercase().contains("upgrade")
             }
         }
-        self.method == Method::CONNECT
+        self.0.method == Method::CONNECT
     }
 
     /// Check if request has chunked transfer encoding
     pub fn chunked(&self) -> Result<bool, ParseError> {
-        if let Some(encodings) = self.headers.get(header::TRANSFER_ENCODING) {
+        if let Some(encodings) = self.0.headers.get(header::TRANSFER_ENCODING) {
             if let Ok(s) = encodings.to_str() {
                 Ok(s.to_lowercase().contains("chunked"))
             } else {
@@ -225,7 +243,7 @@ impl HttpRequest {
     /// Parses Range HTTP header string as per RFC 2616.
     /// `size` is full size of response (file).
     pub fn range(&self, size: u64) -> Result<Vec<HttpRange>, HttpRangeError> {
-        if let Some(range) = self.headers().get(header::RANGE) {
+        if let Some(range) = self.0.headers.get(header::RANGE) {
             HttpRange::parse(unsafe{str::from_utf8_unchecked(range.as_bytes())}, size)
                 .map_err(|e| e.into())
         } else {
@@ -236,25 +254,25 @@ impl HttpRequest {
     /// Returns reference to the associated http payload.
     #[inline]
     pub fn payload(&self) -> &Payload {
-        &self.payload
+        &self.0.payload
     }
 
     /// Returns mutable reference to the associated http payload.
     #[inline]
     pub fn payload_mut(&mut self) -> &mut Payload {
-        &mut self.payload
+        &mut self.as_mut().payload
     }
 
     /// Return payload
     pub fn take_payload(&mut self) -> Payload {
-        mem::replace(&mut self.payload, Payload::empty())
+        mem::replace(&mut self.as_mut().payload, Payload::empty())
     }
     
     /// Return stream to process BODY as multipart.
     ///
     /// Content-type: multipart/form-data;
     pub fn multipart(&self, payload: Payload) -> Result<Multipart, MultipartError> {
-        Ok(Multipart::new(Multipart::boundary(&self.headers)?, payload))
+        Ok(Multipart::new(Multipart::boundary(&self.0.headers)?, payload))
     }
 
     /// Parse `application/x-www-form-urlencoded` encoded body.
@@ -287,7 +305,7 @@ impl HttpRequest {
             }
         }
 
-        if let Some(content_type) = self.headers().get(header::CONTENT_TYPE) {
+        if let Some(content_type) = self.0.headers.get(header::CONTENT_TYPE) {
             if let Ok(content_type) = content_type.to_str() {
                 if content_type.to_lowercase() == "application/x-www-form-urlencoded" {
                     return Ok(UrlEncoded{pl: payload, body: BytesMut::new()})
@@ -299,19 +317,25 @@ impl HttpRequest {
     }
 }
 
+impl Clone for HttpRequest {
+    fn clone(&self) -> HttpRequest {
+        HttpRequest(Rc::clone(&self.0))
+    }
+}
+
 impl fmt::Debug for HttpRequest {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let res = write!(f, "\nHttpRequest {:?} {}:{}\n",
-                         self.version, self.method, self.path);
+                         self.0.version, self.0.method, self.0.path);
         if !self.query_string().is_empty() {
             let _ = write!(f, "  query: ?{:?}\n", self.query_string());
         }
-        if !self.params.is_empty() {
-            let _ = write!(f, "  params: {:?}\n", self.params);
+        if !self.0.params.is_empty() {
+            let _ = write!(f, "  params: {:?}\n", self.0.params);
         }
         let _ = write!(f, "  headers:\n");
-        for key in self.headers.keys() {
-            let vals: Vec<_> = self.headers.get_all(key).iter().collect();
+        for key in self.0.headers.keys() {
+            let vals: Vec<_> = self.0.headers.get_all(key).iter().collect();
             if vals.len() > 1 {
                 let _ = write!(f, "    {:?}: {:?}\n", key, vals);
             } else {
diff --git a/src/pipeline.rs b/src/pipeline.rs
index ef6706cd..518a8213 100644
--- a/src/pipeline.rs
+++ b/src/pipeline.rs
@@ -10,8 +10,8 @@ use h1writer::Writer;
 use httprequest::HttpRequest;
 use httpresponse::HttpResponse;
 
-type Handler = Fn(&mut HttpRequest) -> Task;
-pub(crate) type PipelineHandler<'a> = &'a Fn(&mut HttpRequest) -> Task;
+type Handler = Fn(HttpRequest) -> Task;
+pub(crate) type PipelineHandler<'a> = &'a Fn(HttpRequest) -> Task;
 
 pub struct Pipeline(PipelineState);
 
@@ -26,10 +26,10 @@ enum PipelineState {
 
 impl Pipeline {
 
-    pub fn new(mut req: HttpRequest,
-               mw: Rc<Vec<Box<Middleware>>>, handler: PipelineHandler) -> Pipeline {
+    pub fn new(req: HttpRequest, mw: Rc<Vec<Box<Middleware>>>, handler: PipelineHandler) -> Pipeline
+    {
         if mw.is_empty() {
-            let task = (handler)(&mut req);
+            let task = (handler)(req.clone());
             Pipeline(PipelineState::Task(Box::new((task, req))))
         } else {
             match Start::init(mw, req, handler) {
@@ -191,7 +191,7 @@ impl Start {
         let len = self.middlewares.len();
         loop {
             if self.idx == len {
-                let task = (unsafe{&*self.hnd})(&mut req);
+                let task = (unsafe{&*self.hnd})(req.clone());
                 return Ok(StartResult::Ready(
                     Box::new(Handle::new(self.idx-1, req, self.prepare(task), self.middlewares))))
             } else {
@@ -243,7 +243,7 @@ impl Start {
                             self.prepare(Task::reply(resp)), Rc::clone(&self.middlewares)))))
                     }
                     if self.idx == len {
-                        let task = (unsafe{&*self.hnd})(&mut req);
+                        let task = (unsafe{&*self.hnd})(req.clone());
                         return Ok(Async::Ready(Box::new(Handle::new(
                             self.idx-1, req, self.prepare(task), Rc::clone(&self.middlewares)))))
                     } else {
diff --git a/src/resource.rs b/src/resource.rs
index 234238fd..54f7c43b 100644
--- a/src/resource.rs
+++ b/src/resource.rs
@@ -64,7 +64,7 @@ impl<S> Resource<S> where S: 'static {
 
     /// Register handler for specified method.
     pub fn handler<F, R>(&mut self, method: Method, handler: F)
-        where F: Fn(&mut HttpRequest, &S) -> Result<R> + 'static,
+        where F: Fn(HttpRequest, &S) -> Result<R> + 'static,
               R: Into<HttpResponse> + 'static,
     {
         self.routes.insert(method, Box::new(FnHandler::new(handler)));
@@ -72,7 +72,7 @@ impl<S> Resource<S> where S: 'static {
 
     /// Register async handler for specified method.
     pub fn async<F, R>(&mut self, method: Method, handler: F)
-        where F: Fn(&mut HttpRequest, &S) -> R + 'static,
+        where F: Fn(HttpRequest, &S) -> R + 'static,
               R: Stream<Item=Frame, Error=Error> + 'static,
     {
         self.routes.insert(method, Box::new(StreamHandler::new(handler)));
@@ -125,7 +125,7 @@ impl<S> Resource<S> where S: 'static {
 
 impl<S: 'static> RouteHandler<S> for Resource<S> {
 
-    fn handle(&self, req: &mut HttpRequest, state: Rc<S>) -> Task {
+    fn handle(&self, req: HttpRequest, state: Rc<S>) -> Task {
         if let Some(handler) = self.routes.get(req.method()) {
             handler.handle(req, state)
         } else {
diff --git a/src/route.rs b/src/route.rs
index 34c8df90..3a1ccfd8 100644
--- a/src/route.rs
+++ b/src/route.rs
@@ -33,7 +33,7 @@ impl Frame {
 #[allow(unused_variables)]
 pub trait RouteHandler<S>: 'static {
     /// Handle request
-    fn handle(&self, req: &mut HttpRequest, state: Rc<S>) -> Task;
+    fn handle(&self, req: HttpRequest, state: Rc<S>) -> Task;
 
     /// Set route prefix
     fn set_prefix(&mut self, prefix: String) {}
@@ -50,7 +50,7 @@ pub trait Route: Actor {
     type State;
 
     /// Handle `EXPECT` header. By default respones with `HTTP/1.1 100 Continue`
-    fn expect(req: &HttpRequest, ctx: &mut Self::Context) -> Result<(), Error>
+    fn expect(req: &mut HttpRequest, ctx: &mut Self::Context) -> Result<(), Error>
         where Self: Actor<Context=HttpContext<Self>>
     {
         // handle expect header only for HTTP/1.1
@@ -80,7 +80,7 @@ pub trait Route: Actor {
     /// request/response or websocket connection.
     /// In that case `HttpContext::start` and `HttpContext::write` has to be used
     /// for writing response.
-    fn request(req: &mut HttpRequest, ctx: &mut Self::Context) -> RouteResult<Self>;
+    fn request(req: HttpRequest, ctx: &mut Self::Context) -> RouteResult<Self>;
 
     /// This method creates `RouteFactory` for this actor.
     fn factory() -> RouteFactory<Self, Self::State> {
@@ -95,12 +95,12 @@ impl<A, S> RouteHandler<S> for RouteFactory<A, S>
     where A: Actor<Context=HttpContext<A>> + Route<State=S>,
           S: 'static
 {
-    fn handle(&self, req: &mut HttpRequest, state: Rc<A::State>) -> Task {
+    fn handle(&self, mut req: HttpRequest, state: Rc<A::State>) -> Task {
         let mut ctx = HttpContext::new(state);
 
         // handle EXPECT header
         if req.headers().contains_key(header::EXPECT) {
-            if let Err(resp) = A::expect(req, &mut ctx) {
+            if let Err(resp) = A::expect(&mut req, &mut ctx) {
                 return Task::reply(resp)
             }
         }
@@ -114,7 +114,7 @@ impl<A, S> RouteHandler<S> for RouteFactory<A, S>
 /// Fn() route handler
 pub(crate)
 struct FnHandler<S, R, F>
-    where F: Fn(&mut HttpRequest, &S) -> R + 'static,
+    where F: Fn(HttpRequest, &S) -> R + 'static,
           R: Into<HttpResponse>,
           S: 'static,
 {
@@ -123,7 +123,7 @@ struct FnHandler<S, R, F>
 }
 
 impl<S, R, F> FnHandler<S, R, F>
-    where F: Fn(&mut HttpRequest, &S) -> R + 'static,
+    where F: Fn(HttpRequest, &S) -> R + 'static,
           R: Into<HttpResponse> + 'static,
           S: 'static,
 {
@@ -133,11 +133,11 @@ impl<S, R, F> FnHandler<S, R, F>
 }
 
 impl<S, R, F> RouteHandler<S> for FnHandler<S, R, F>
-    where F: Fn(&mut HttpRequest, &S) -> R + 'static,
+    where F: Fn(HttpRequest, &S) -> R + 'static,
           R: Into<HttpResponse> + 'static,
           S: 'static,
 {
-    fn handle(&self, req: &mut HttpRequest, state: Rc<S>) -> Task {
+    fn handle(&self, req: HttpRequest, state: Rc<S>) -> Task {
         Task::reply((self.f)(req, &state).into())
     }
 }
@@ -145,7 +145,7 @@ impl<S, R, F> RouteHandler<S> for FnHandler<S, R, F>
 /// Async route handler
 pub(crate)
 struct StreamHandler<S, R, F>
-    where F: Fn(&mut HttpRequest, &S) -> R + 'static,
+    where F: Fn(HttpRequest, &S) -> R + 'static,
           R: Stream<Item=Frame, Error=Error> + 'static,
           S: 'static,
 {
@@ -154,7 +154,7 @@ struct StreamHandler<S, R, F>
 }
 
 impl<S, R, F> StreamHandler<S, R, F>
-    where F: Fn(&mut HttpRequest, &S) -> R + 'static,
+    where F: Fn(HttpRequest, &S) -> R + 'static,
           R: Stream<Item=Frame, Error=Error> + 'static,
           S: 'static,
 {
@@ -164,11 +164,11 @@ impl<S, R, F> StreamHandler<S, R, F>
 }
 
 impl<S, R, F> RouteHandler<S> for StreamHandler<S, R, F>
-    where F: Fn(&mut HttpRequest, &S) -> R + 'static,
+    where F: Fn(HttpRequest, &S) -> R + 'static,
           R: Stream<Item=Frame, Error=Error> + 'static,
           S: 'static,
 {
-    fn handle(&self, req: &mut HttpRequest, state: Rc<S>) -> Task {
+    fn handle(&self, req: HttpRequest, state: Rc<S>) -> Task {
         Task::with_stream((self.f)(req, &state))
     }
 }
diff --git a/src/staticfiles.rs b/src/staticfiles.rs
index cfc9b7a1..97cd4407 100644
--- a/src/staticfiles.rs
+++ b/src/staticfiles.rs
@@ -137,7 +137,7 @@ impl<S: 'static> RouteHandler<S> for StaticFiles {
         }
     }
 
-    fn handle(&self, req: &mut HttpRequest, _: Rc<S>) -> Task {
+    fn handle(&self, req: HttpRequest, _: Rc<S>) -> Task {
         if !self.accessible {
             Task::reply(HTTPNotFound)
         } else {
diff --git a/src/ws.rs b/src/ws.rs
index 97769e03..91024819 100644
--- a/src/ws.rs
+++ b/src/ws.rs
@@ -22,14 +22,14 @@
 //! impl Route for WsRoute {
 //!     type State = ();
 //!
-//!     fn request(req: &mut HttpRequest, ctx: &mut HttpContext<Self>) -> RouteResult<Self>
+//!     fn request(mut req: HttpRequest, ctx: &mut HttpContext<Self>) -> RouteResult<Self>
 //!     {
 //!         // WebSocket handshake
 //!         let resp = ws::handshake(&req)?;
 //!         // Send handshake response to peer
 //!         ctx.start(resp);
 //!         // Map Payload into WsStream
-//!         ctx.add_stream(ws::WsStream::new(req));
+//!         ctx.add_stream(ws::WsStream::new(&mut req));
 //!         // Start ws messages processing
 //!         Reply::async(WsRoute)
 //!     }