diff --git a/src/encoding.rs b/src/encoding.rs
index 4774b4c7..2768dfd1 100644
--- a/src/encoding.rs
+++ b/src/encoding.rs
@@ -346,7 +346,7 @@ impl PayloadEncoder {
         };
 
         // Enable content encoding only if response does not contain Content-Encoding header
-        let mut encoding = if has_body && !resp.headers.contains_key(CONTENT_ENCODING) {
+        let mut encoding = if has_body && !resp.headers().contains_key(CONTENT_ENCODING) {
             let encoding = match *resp.content_encoding() {
                 ContentEncoding::Auto => {
                     // negotiate content-encoding
@@ -362,7 +362,8 @@ impl PayloadEncoder {
                 }
                 encoding => encoding,
             };
-            resp.headers.insert(CONTENT_ENCODING, HeaderValue::from_static(encoding.as_str()));
+            resp.headers_mut().insert(
+                CONTENT_ENCODING, HeaderValue::from_static(encoding.as_str()));
             encoding
         } else {
             ContentEncoding::Identity
@@ -377,8 +378,8 @@ impl PayloadEncoder {
                 if resp.chunked() {
                     error!("Chunked transfer is enabled but body is set to Empty");
                 }
-                resp.headers.insert(CONTENT_LENGTH, HeaderValue::from_static("0"));
-                resp.headers.remove(TRANSFER_ENCODING);
+                resp.headers_mut().insert(CONTENT_LENGTH, HeaderValue::from_static("0"));
+                resp.headers_mut().remove(TRANSFER_ENCODING);
                 TransferEncoding::length(0)
             },
             Body::Binary(ref mut bytes) => {
@@ -399,31 +400,31 @@ impl PayloadEncoder {
                     let _ = enc.write_eof();
                     let b = enc.get_mut().take();
 
-                    resp.headers.insert(
+                    resp.headers_mut().insert(
                         CONTENT_LENGTH,
                         HeaderValue::from_str(format!("{}", b.len()).as_str()).unwrap());
                     *bytes = Binary::from(b);
                     encoding = ContentEncoding::Identity;
                     TransferEncoding::eof()
                 } else {
-                    resp.headers.insert(
+                    resp.headers_mut().insert(
                         CONTENT_LENGTH,
                         HeaderValue::from_str(format!("{}", bytes.len()).as_str()).unwrap());
-                    resp.headers.remove(TRANSFER_ENCODING);
+                    resp.headers_mut().remove(TRANSFER_ENCODING);
                     TransferEncoding::length(bytes.len() as u64)
                 }
             }
             Body::Streaming(_) | Body::StreamingContext => {
                 if resp.chunked() {
-                    resp.headers.remove(CONTENT_LENGTH);
+                    resp.headers_mut().remove(CONTENT_LENGTH);
                     if version != Version::HTTP_11 {
                         error!("Chunked transfer encoding is forbidden for {:?}", version);
                     }
                     if version == Version::HTTP_2 {
-                        resp.headers.remove(TRANSFER_ENCODING);
+                        resp.headers_mut().remove(TRANSFER_ENCODING);
                         TransferEncoding::eof()
                     } else {
-                        resp.headers.insert(
+                        resp.headers_mut().insert(
                             TRANSFER_ENCODING, HeaderValue::from_static("chunked"));
                         TransferEncoding::chunked()
                     }
@@ -447,11 +448,12 @@ impl PayloadEncoder {
                 if version == Version::HTTP_2 {
                     error!("Connection upgrade is forbidden for HTTP/2");
                 } else {
-                    resp.headers.insert(CONNECTION, HeaderValue::from_static("upgrade"));
+                    resp.headers_mut().insert(
+                        CONNECTION, HeaderValue::from_static("upgrade"));
                 }
                 if encoding != ContentEncoding::Identity {
                     encoding = ContentEncoding::Identity;
-                    resp.headers.remove(CONTENT_ENCODING);
+                    resp.headers_mut().remove(CONTENT_ENCODING);
                 }
                 TransferEncoding::eof()
             }
diff --git a/src/h1writer.rs b/src/h1writer.rs
index 63c98e87..447758cf 100644
--- a/src/h1writer.rs
+++ b/src/h1writer.rs
@@ -116,7 +116,7 @@ impl<T: AsyncWrite> Writer for H1Writer<T> {
     fn start(&mut self, req: &mut HttpRequest, msg: &mut HttpResponse)
              -> Result<WriterState, io::Error>
     {
-        trace!("Prepare response with status: {:?}", msg.status);
+        trace!("Prepare response with status: {:?}", msg.status());
 
         // prepare task
         self.started = true;
@@ -126,32 +126,32 @@ impl<T: AsyncWrite> Writer for H1Writer<T> {
         // Connection upgrade
         let version = msg.version().unwrap_or_else(|| req.version());
         if msg.upgrade() {
-            msg.headers.insert(CONNECTION, HeaderValue::from_static("upgrade"));
+            msg.headers_mut().insert(CONNECTION, HeaderValue::from_static("upgrade"));
         }
         // keep-alive
         else if self.keepalive {
             if version < Version::HTTP_11 {
-                msg.headers.insert(CONNECTION, HeaderValue::from_static("keep-alive"));
+                msg.headers_mut().insert(CONNECTION, HeaderValue::from_static("keep-alive"));
             }
         } else if version >= Version::HTTP_11 {
-            msg.headers.insert(CONNECTION, HeaderValue::from_static("close"));
+            msg.headers_mut().insert(CONNECTION, HeaderValue::from_static("close"));
         }
 
         // render message
         {
             let buffer = self.encoder.get_mut();
             if let Body::Binary(ref bytes) = *msg.body() {
-                buffer.reserve(100 + msg.headers.len() * AVERAGE_HEADER_SIZE + bytes.len());
+                buffer.reserve(100 + msg.headers().len() * AVERAGE_HEADER_SIZE + bytes.len());
             } else {
-                buffer.reserve(100 + msg.headers.len() * AVERAGE_HEADER_SIZE);
+                buffer.reserve(100 + msg.headers().len() * AVERAGE_HEADER_SIZE);
             }
 
-            if version == Version::HTTP_11 && msg.status == StatusCode::OK {
+            if version == Version::HTTP_11 && msg.status() == StatusCode::OK {
                 buffer.extend(b"HTTP/1.1 200 OK\r\n");
             } else {
-                let _ = write!(buffer, "{:?} {}\r\n", version, msg.status);
+                let _ = write!(buffer, "{:?} {}\r\n", version, msg.status());
             }
-            for (key, value) in &msg.headers {
+            for (key, value) in msg.headers() {
                 let t: &[u8] = key.as_ref();
                 buffer.extend(t);
                 buffer.extend(b": ");
@@ -161,7 +161,7 @@ impl<T: AsyncWrite> Writer for H1Writer<T> {
 
             // using http::h1::date is quite a lot faster than generating
             // a unique Date header each time like req/s goes up about 10%
-            if !msg.headers.contains_key(DATE) {
+            if !msg.headers().contains_key(DATE) {
                 buffer.reserve(date::DATE_VALUE_LENGTH + 8);
                 buffer.extend(b"Date: ");
                 let mut bytes = [0u8; 29];
@@ -171,7 +171,7 @@ impl<T: AsyncWrite> Writer for H1Writer<T> {
             }
 
             // default content-type
-            if !msg.headers.contains_key(CONTENT_TYPE) {
+            if !msg.headers().contains_key(CONTENT_TYPE) {
                 buffer.extend(b"ContentType: application/octet-stream\r\n".as_ref());
             }
 
diff --git a/src/h2writer.rs b/src/h2writer.rs
index e3e04bd7..82a1b96e 100644
--- a/src/h2writer.rs
+++ b/src/h2writer.rs
@@ -108,7 +108,7 @@ impl Writer for H2Writer {
     fn start(&mut self, req: &mut HttpRequest, msg: &mut HttpResponse)
              -> Result<WriterState, io::Error>
     {
-        trace!("Prepare response with status: {:?}", msg.status);
+        trace!("Prepare response with status: {:?}", msg.status());
 
         // prepare response
         self.started = true;
@@ -116,25 +116,25 @@ impl Writer for H2Writer {
         self.eof = if let Body::Empty = *msg.body() { true } else { false };
 
         // http2 specific
-        msg.headers.remove(CONNECTION);
-        msg.headers.remove(TRANSFER_ENCODING);
+        msg.headers_mut().remove(CONNECTION);
+        msg.headers_mut().remove(TRANSFER_ENCODING);
 
         // using http::h1::date is quite a lot faster than generating
         // a unique Date header each time like req/s goes up about 10%
-        if !msg.headers.contains_key(DATE) {
+        if !msg.headers().contains_key(DATE) {
             let mut bytes = [0u8; 29];
             date::extend(&mut bytes[..]);
-            msg.headers.insert(DATE, HeaderValue::try_from(&bytes[..]).unwrap());
+            msg.headers_mut().insert(DATE, HeaderValue::try_from(&bytes[..]).unwrap());
         }
 
         // default content-type
-        if !msg.headers.contains_key(CONTENT_TYPE) {
-            msg.headers.insert(
+        if !msg.headers().contains_key(CONTENT_TYPE) {
+            msg.headers_mut().insert(
                 CONTENT_TYPE, HeaderValue::from_static("application/octet-stream"));
         }
 
         let mut resp = Response::new(());
-        *resp.status_mut() = msg.status;
+        *resp.status_mut() = msg.status();
         *resp.version_mut() = Version::HTTP_2;
         for (key, value) in msg.headers().iter() {
             resp.headers_mut().insert(key, value.clone());
diff --git a/src/httprequest.rs b/src/httprequest.rs
index 284adf9c..36dcf22c 100644
--- a/src/httprequest.rs
+++ b/src/httprequest.rs
@@ -97,11 +97,13 @@ impl<S> HttpRequest<S> {
         HttpRequest(Rc::clone(&self.0), Rc::new(()), None)
     }
 
-    /// get mutable reference for inner message
+    // get mutable reference for inner message
+    // mutable reference should not be returned as result for request's method
     #[inline]
-    fn as_mut(&mut self) -> &mut HttpMessage {
+    #[allow(mutable_transmutes)]
+    #[cfg_attr(feature = "cargo-clippy", allow(mut_from_ref))]
+    fn as_mut(&self) -> &mut HttpMessage {
         let r: &HttpMessage = self.0.as_ref();
-        #[allow(mutable_transmutes)]
         unsafe{mem::transmute(r)}
     }
 
@@ -158,18 +160,8 @@ impl<S> HttpRequest<S> {
         self.0.uri.path()
     }
 
-    /// Get previously loaded *ConnectionInfo*.
-    #[inline]
-    pub fn connection_info(&self) -> Option<&ConnectionInfo> {
-        if self.0.info.is_none() {
-            None
-        } else {
-            self.0.info.as_ref()
-        }
-    }
-
-    /// Load *ConnectionInfo* for currect request.
-    pub fn load_connection_info(&mut self) -> &ConnectionInfo {
+    /// Get *ConnectionInfo* for currect request.
+    pub fn connection_info(&self) -> &ConnectionInfo {
         if self.0.info.is_none() {
             let info: ConnectionInfo<'static> = unsafe{
                 mem::transmute(ConnectionInfo::new(self))};
@@ -178,7 +170,7 @@ impl<S> HttpRequest<S> {
         self.0.info.as_ref().unwrap()
     }
 
-    pub fn url_for<U, I>(&mut self, name: &str, elements: U) -> Result<Url, UrlGenerationError>
+    pub fn url_for<U, I>(&self, name: &str, elements: U) -> Result<Url, UrlGenerationError>
         where U: IntoIterator<Item=I>,
               I: AsRef<str>,
     {
@@ -187,7 +179,7 @@ impl<S> HttpRequest<S> {
         } else {
             let path = self.router().unwrap().resource_path(name, elements)?;
             if path.starts_with('/') {
-                let conn = self.load_connection_info();
+                let conn = self.connection_info();
                 Ok(Url::parse(&format!("{}://{}{}", conn.scheme(), conn.host(), path))?)
             } else {
                 Ok(Url::parse(&path)?)
diff --git a/src/httpresponse.rs b/src/httpresponse.rs
index 0f01d96f..e877a761 100644
--- a/src/httpresponse.rs
+++ b/src/httpresponse.rs
@@ -29,9 +29,9 @@ pub enum ConnectionType {
 
 /// An HTTP Response
 pub struct HttpResponse {
-    pub version: Option<Version>,
-    pub headers: HeaderMap,
-    pub status: StatusCode,
+    version: Option<Version>,
+    headers: HeaderMap,
+    status: StatusCode,
     reason: Option<&'static str>,
     body: Body,
     chunked: bool,
diff --git a/src/middlewares/logger.rs b/src/middlewares/logger.rs
index a18e8ad1..5e443fce 100644
--- a/src/middlewares/logger.rs
+++ b/src/middlewares/logger.rs
@@ -102,7 +102,6 @@ impl Logger {
 impl Middleware for Logger {
 
     fn start(&self, req: &mut HttpRequest) -> Started {
-        req.load_connection_info();
         req.extensions().insert(StartTime(time::now()));
         Started::Done
     }
@@ -237,12 +236,11 @@ impl FormatText {
                 fmt.write_fmt(format_args!("{:.6}", response_time_ms))
             },
             FormatText::RemoteAddr => {
-                if let Some(addr) = req.connection_info() {
-                    if let Some(remote) = addr.remote() {
-                        return remote.fmt(fmt);
-                    }
+                if let Some(remote) = req.connection_info().remote() {
+                    return remote.fmt(fmt);
+                } else {
+                    "-".fmt(fmt)
                 }
-                "-".fmt(fmt)
             }
             FormatText::RequestTime => {
                 entry_time.strftime("[%d/%b/%Y:%H:%M:%S %z]")