diff --git a/src/httprequest.rs b/src/httprequest.rs
index 6ab0e9cb..803171de 100644
--- a/src/httprequest.rs
+++ b/src/httprequest.rs
@@ -1,5 +1,6 @@
 //! Pieces pertaining to the HTTP message protocol.
 use std::{io, str};
+use url::form_urlencoded;
 use http::{header, Method, Version, Uri, HeaderMap};
 
 use Params;
@@ -65,10 +66,18 @@ impl HttpRequest {
         self.uri.path()
     }
 
-    /// The query string of this Request.
+    /// Return a new iterator that yields pairs of `Cow<str>` for query parameters
     #[inline]
-    pub fn query(&self) -> Option<&str> {
-        self.uri.query()
+    pub fn query(&self) -> form_urlencoded::Parse {
+        form_urlencoded::parse(self.query_string().as_ref())
+    }
+
+    /// The query string in the URL.
+    ///
+    /// E.g., id=10
+    #[inline]
+    pub fn query_string(&self) -> &str {
+        self.uri.query().unwrap_or("")
     }
 
     /// Return request cookies.
diff --git a/tests/test_httpmessage.rs b/tests/test_httprequest.rs
similarity index 65%
rename from tests/test_httpmessage.rs
rename to tests/test_httprequest.rs
index 98004c7d..0802a5c7 100644
--- a/tests/test_httpmessage.rs
+++ b/tests/test_httprequest.rs
@@ -3,7 +3,6 @@ extern crate http;
 extern crate time;
 
 use actix_web::*;
-use time::Duration;
 use http::{header, Method, Uri, Version, HeaderMap, HttpTryFrom};
 
 
@@ -44,38 +43,6 @@ fn test_request_cookies() {
     assert!(cookie.is_none());
 }
 
-#[test]
-fn test_response_cookies() {
-    let mut headers = HeaderMap::new();
-    headers.insert(header::COOKIE,
-                   header::HeaderValue::from_static("cookie1=value1; cookie2=value2"));
-
-    let mut req = HttpRequest::new(
-        Method::GET, Uri::try_from("/").unwrap(), Version::HTTP_11, headers);
-    let cookies = req.load_cookies().unwrap();
-
-    let resp = httpcodes::HTTPOk
-        .builder()
-        .cookie(Cookie::build("name", "value")
-                .domain("www.rust-lang.org")
-                .path("/test")
-                .http_only(true)
-                .max_age(Duration::days(1))
-                .finish())
-        .del_cookie(&cookies[0])
-        .body(Body::Empty);
-
-    assert!(resp.is_ok());
-    let resp = resp.unwrap();
-
-    let mut val: Vec<_> = resp.headers().get_all("Set-Cookie")
-        .iter().map(|v| v.to_str().unwrap().to_owned()).collect();
-    val.sort();
-    assert!(val[0].starts_with("cookie1=; Max-Age=0;"));
-    assert_eq!(
-        val[1],"name=value; HttpOnly; Path=/test; Domain=www.rust-lang.org; Max-Age=86400");
-}
-
 #[test]
 fn test_no_request_range_header() {
     let req = HttpRequest::new(Method::GET, Uri::try_from("/").unwrap(),
@@ -97,3 +64,14 @@ fn test_request_range_header() {
     assert_eq!(ranges[0].start, 0);
     assert_eq!(ranges[0].length, 5);
 }
+
+#[test]
+fn test_request_query() {
+    let req = HttpRequest::new(Method::GET, Uri::try_from("/?id=test").unwrap(),
+                               Version::HTTP_11, HeaderMap::new());
+
+    assert_eq!(req.query_string(), "id=test");
+    let query: Vec<_> = req.query().collect();
+    assert_eq!(query[0].0.as_ref(), "id");
+    assert_eq!(query[0].1.as_ref(), "test");
+}
diff --git a/tests/test_httpresponse.rs b/tests/test_httpresponse.rs
new file mode 100644
index 00000000..e4805cc1
--- /dev/null
+++ b/tests/test_httpresponse.rs
@@ -0,0 +1,40 @@
+extern crate actix_web;
+extern crate http;
+extern crate time;
+
+use actix_web::*;
+use time::Duration;
+use http::{header, Method, Uri, Version, HeaderMap, HttpTryFrom};
+
+
+#[test]
+fn test_response_cookies() {
+    let mut headers = HeaderMap::new();
+    headers.insert(header::COOKIE,
+                   header::HeaderValue::from_static("cookie1=value1; cookie2=value2"));
+
+    let mut req = HttpRequest::new(
+        Method::GET, Uri::try_from("/").unwrap(), Version::HTTP_11, headers);
+    let cookies = req.load_cookies().unwrap();
+
+    let resp = httpcodes::HTTPOk
+        .builder()
+        .cookie(Cookie::build("name", "value")
+                .domain("www.rust-lang.org")
+                .path("/test")
+                .http_only(true)
+                .max_age(Duration::days(1))
+                .finish())
+        .del_cookie(&cookies[0])
+        .body(Body::Empty);
+
+    assert!(resp.is_ok());
+    let resp = resp.unwrap();
+
+    let mut val: Vec<_> = resp.headers().get_all("Set-Cookie")
+        .iter().map(|v| v.to_str().unwrap().to_owned()).collect();
+    val.sort();
+    assert!(val[0].starts_with("cookie1=; Max-Age=0;"));
+    assert_eq!(
+        val[1],"name=value; HttpOnly; Path=/test; Domain=www.rust-lang.org; Max-Age=86400");
+}