mirror of https://github.com/rwf2/Rocket.git
Remove dependence from Hyper in Request/MockRequest.
This commit is contained in:
parent
a73a082153
commit
08f41816d1
|
@ -1,11 +1,12 @@
|
||||||
use super::rocket;
|
use super::rocket;
|
||||||
use rocket::testing::MockRequest;
|
use rocket::testing::MockRequest;
|
||||||
use rocket::http::Method::*;
|
use rocket::http::Method::*;
|
||||||
|
use rocket::http::ContentType;
|
||||||
|
|
||||||
fn test_login<F: Fn(String) -> bool>(username: &str, password: &str, age: isize, test: F) {
|
fn test_login<F: Fn(String) -> bool>(username: &str, password: &str, age: isize, test: F) {
|
||||||
let rocket = rocket::ignite().mount("/", routes![super::user_page, super::login]);
|
let rocket = rocket::ignite().mount("/", routes![super::user_page, super::login]);
|
||||||
let result = MockRequest::new(Post, "/login")
|
let result = MockRequest::new(Post, "/login")
|
||||||
.headers(&[("Content-Type", "application/x-www-form-urlencoded")])
|
.header(ContentType::Form)
|
||||||
.body(&format!("username={}&password={}&age={}", username, password, age))
|
.body(&format!("username={}&password={}&age={}", username, password, age))
|
||||||
.dispatch_with(&rocket)
|
.dispatch_with(&rocket)
|
||||||
.unwrap_or("".to_string());
|
.unwrap_or("".to_string());
|
||||||
|
|
|
@ -37,14 +37,20 @@ mod test {
|
||||||
use super::rocket;
|
use super::rocket;
|
||||||
use rocket::testing::MockRequest;
|
use rocket::testing::MockRequest;
|
||||||
use rocket::http::Method::*;
|
use rocket::http::Method::*;
|
||||||
|
use rocket::http::Header;
|
||||||
|
|
||||||
|
fn test_header_count<'h>(headers: Vec<Header<'static>>) {
|
||||||
|
let num_headers = headers.len();
|
||||||
|
let mut req = MockRequest::new(Get, "/");
|
||||||
|
for header in headers {
|
||||||
|
req = req.header(header);
|
||||||
|
}
|
||||||
|
|
||||||
fn test_header_count<'h>(headers: &[(&'h str, &'h str)]) {
|
|
||||||
// FIXME: Should be able to count headers directly!
|
// FIXME: Should be able to count headers directly!
|
||||||
let rocket = rocket::ignite().mount("/", routes![super::header_count]);
|
let rocket = rocket::ignite().mount("/", routes![super::header_count]);
|
||||||
let mut req = MockRequest::new(Get, "/").headers(headers);
|
|
||||||
let result = req.dispatch_with(&rocket);
|
let result = req.dispatch_with(&rocket);
|
||||||
assert_eq!(result.unwrap(),
|
assert_eq!(result.unwrap(),
|
||||||
format!("Your request contained {} headers!", headers.len()));
|
format!("Your request contained {} headers!", num_headers));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -53,14 +59,10 @@ mod test {
|
||||||
let mut headers = vec![];
|
let mut headers = vec![];
|
||||||
for j in 0..i {
|
for j in 0..i {
|
||||||
let string = format!("{}", j);
|
let string = format!("{}", j);
|
||||||
headers.push((string.clone(), string));
|
headers.push(Header::new(string.clone(), string));
|
||||||
}
|
}
|
||||||
|
|
||||||
let h_strs: Vec<_> = headers.iter()
|
test_header_count(headers);
|
||||||
.map(|&(ref a, ref b)| (a.as_str(), b.as_str()))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
test_header_count(&h_strs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,19 +46,44 @@ impl<'h> HeaderMap<'h> {
|
||||||
HeaderMap { headers: HashMap::new() }
|
HeaderMap { headers: HashMap::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
|
pub fn contains(&self, name: &str) -> bool {
|
||||||
|
self.headers.get(name).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.headers.iter().flat_map(|(_, values)| values.iter()).count()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn get<'a>(&'a self, name: &str) -> impl Iterator<Item=&'a str> {
|
pub fn get<'a>(&'a self, name: &str) -> impl Iterator<Item=&'a str> {
|
||||||
self.headers.get(name).into_iter().flat_map(|values| {
|
self.headers.get(name).into_iter().flat_map(|values| {
|
||||||
values.iter().map(|val| val.borrow())
|
values.iter().map(|val| val.borrow())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get_one<'a>(&'a self, name: &str) -> Option<&'a str> {
|
||||||
|
self.headers.get(name).and_then(|values| {
|
||||||
|
if values.len() >= 1 { Some(values[0].borrow()) }
|
||||||
|
else { None }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn replace<'p: 'h, H: Into<Header<'p>>>(&mut self, header: H) -> bool {
|
pub fn replace<'p: 'h, H: Into<Header<'p>>>(&mut self, header: H) -> bool {
|
||||||
let header = header.into();
|
let header = header.into();
|
||||||
self.headers.insert(header.name, vec![header.value]).is_some()
|
self.headers.insert(header.name, vec![header.value]).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn replace_raw<'a: 'h, 'b: 'h, N, V>(&mut self, name: N, value: V) -> bool
|
||||||
|
where N: Into<Cow<'a, str>>, V: Into<Cow<'b, str>>
|
||||||
|
{
|
||||||
|
self.replace(Header::new(name, value))
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn replace_all<'n, 'v: 'h, H>(&mut self, name: H, values: Vec<Cow<'v, str>>)
|
pub fn replace_all<'n, 'v: 'h, H>(&mut self, name: H, values: Vec<Cow<'v, str>>)
|
||||||
where 'n: 'h, H: Into<Cow<'n, str>>
|
where 'n: 'h, H: Into<Cow<'n, str>>
|
||||||
|
@ -72,6 +97,13 @@ impl<'h> HeaderMap<'h> {
|
||||||
self.headers.entry(header.name).or_insert(vec![]).push(header.value);
|
self.headers.entry(header.name).or_insert(vec![]).push(header.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn add_raw<'a: 'h, 'b: 'h, N, V>(&mut self, name: N, value: V)
|
||||||
|
where N: Into<Cow<'a, str>>, V: Into<Cow<'b, str>>
|
||||||
|
{
|
||||||
|
self.add(Header::new(name, value))
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn add_all<'n, H>(&mut self, name: H, values: &mut Vec<Cow<'h, str>>)
|
pub fn add_all<'n, H>(&mut self, name: H, values: &mut Vec<Cow<'h, str>>)
|
||||||
where 'n:'h, H: Into<Cow<'n, str>>
|
where 'n:'h, H: Into<Cow<'n, str>>
|
||||||
|
@ -85,6 +117,11 @@ impl<'h> HeaderMap<'h> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
pub fn remove_all(&mut self) -> Vec<Header<'h>> {
|
||||||
|
let old_map = ::std::mem::replace(self, HeaderMap::new());
|
||||||
|
old_map.into_iter().collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn iter<'s>(&'s self) -> impl Iterator<Item=Header<'s>> {
|
pub fn iter<'s>(&'s self) -> impl Iterator<Item=Header<'s>> {
|
||||||
self.headers.iter().flat_map(|(key, values)| {
|
self.headers.iter().flat_map(|(key, values)| {
|
||||||
values.iter().map(move |val| {
|
values.iter().map(move |val| {
|
||||||
|
@ -94,7 +131,20 @@ impl<'h> HeaderMap<'h> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn into_iter<'s>(self)
|
pub fn into_iter(self) -> impl Iterator<Item=Header<'h>> {
|
||||||
|
self.headers.into_iter().flat_map(|(name, value)| {
|
||||||
|
value.into_iter().map(move |value| {
|
||||||
|
Header {
|
||||||
|
name: name.clone(),
|
||||||
|
value: value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn into_iter_raw<'s>(self)
|
||||||
-> impl Iterator<Item=(Cow<'h, str>, Vec<Cow<'h, str>>)> {
|
-> impl Iterator<Item=(Cow<'h, str>, Vec<Cow<'h, str>>)> {
|
||||||
self.headers.into_iter()
|
self.headers.into_iter()
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,8 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
|
||||||
/// ensure that the handlers corresponding to these requests don't get called
|
/// ensure that the handlers corresponding to these requests don't get called
|
||||||
/// unless there is an API key in the request and the key is valid. The
|
/// unless there is an API key in the request and the key is valid. The
|
||||||
/// following example implements this using an `APIKey` type and a `FromRequest`
|
/// following example implements this using an `APIKey` type and a `FromRequest`
|
||||||
/// implementation for that type in the `senstive` handler:
|
/// implementation for that type. The `APIKey` type is then used in the
|
||||||
|
/// `senstive` handler.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(plugin)]
|
/// # #![feature(plugin)]
|
||||||
|
@ -90,20 +91,19 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
|
||||||
///
|
///
|
||||||
/// impl<'r> FromRequest<'r> for APIKey {
|
/// impl<'r> FromRequest<'r> for APIKey {
|
||||||
/// type Error = ();
|
/// type Error = ();
|
||||||
/// fn from_request(request: &'r Request) -> request::Outcome<APIKey, ()> {
|
|
||||||
/// if let Some(keys) = request.headers().get_raw("x-api-key") {
|
|
||||||
/// if keys.len() != 1 {
|
|
||||||
/// return Outcome::Failure((Status::BadRequest, ()));
|
|
||||||
/// }
|
|
||||||
///
|
///
|
||||||
/// if let Ok(key) = String::from_utf8(keys[0].clone()) {
|
/// fn from_request(request: &'r Request) -> request::Outcome<APIKey, ()> {
|
||||||
/// if is_valid(&key) {
|
/// let keys: Vec<_> = request.headers().get("x-api-key").collect();
|
||||||
/// return Outcome::Success(APIKey(key));
|
/// if keys.len() != 1 {
|
||||||
/// }
|
/// return Outcome::Failure((Status::BadRequest, ()));
|
||||||
/// }
|
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// Outcome::Forward(())
|
/// let key = keys[0];
|
||||||
|
/// if !is_valid(keys[0]) {
|
||||||
|
/// return Outcome::Forward(());
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// return Outcome::Success(APIKey(key.to_string()));
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
|
|
|
@ -9,8 +9,9 @@ use super::{FromParam, FromSegments};
|
||||||
|
|
||||||
use router::Route;
|
use router::Route;
|
||||||
use http::uri::{URI, URIBuf, Segments};
|
use http::uri::{URI, URIBuf, Segments};
|
||||||
use http::hyper::{self, header};
|
use http::{Method, ContentType, Header, HeaderMap, Cookies};
|
||||||
use http::{Method, ContentType, Cookies};
|
|
||||||
|
use http::hyper;
|
||||||
|
|
||||||
/// The type of an incoming web request.
|
/// The type of an incoming web request.
|
||||||
///
|
///
|
||||||
|
@ -25,7 +26,8 @@ pub struct Request {
|
||||||
uri: URIBuf, // FIXME: Should be URI (without hyper).
|
uri: URIBuf, // FIXME: Should be URI (without hyper).
|
||||||
params: RefCell<Vec<&'static str>>,
|
params: RefCell<Vec<&'static str>>,
|
||||||
cookies: Cookies,
|
cookies: Cookies,
|
||||||
headers: header::Headers, // Don't use hyper's headers.
|
// TODO: Allow non-static here.
|
||||||
|
headers: HeaderMap<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Request {
|
impl Request {
|
||||||
|
@ -78,7 +80,8 @@ impl Request {
|
||||||
/// For example, if the request URI is `"/hello/there/i/am/here"`, then
|
/// For example, if the request URI is `"/hello/there/i/am/here"`, then
|
||||||
/// `request.get_segments::<T>(1)` will attempt to parse the segments
|
/// `request.get_segments::<T>(1)` will attempt to parse the segments
|
||||||
/// `"there/i/am/here"` as type `T`.
|
/// `"there/i/am/here"` as type `T`.
|
||||||
pub fn get_segments<'r, T: FromSegments<'r>>(&'r self, i: usize) -> Result<T, Error> {
|
pub fn get_segments<'r, T: FromSegments<'r>>(&'r self, i: usize)
|
||||||
|
-> Result<T, Error> {
|
||||||
let segments = self.get_raw_segments(i).ok_or(Error::NoKey)?;
|
let segments = self.get_raw_segments(i).ok_or(Error::NoKey)?;
|
||||||
T::from_segments(segments).map_err(|_| Error::BadParse)
|
T::from_segments(segments).map_err(|_| Error::BadParse)
|
||||||
}
|
}
|
||||||
|
@ -98,7 +101,7 @@ impl Request {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Implement a testing framework for Rocket.
|
// FIXME: Make this `new`. Make current `new` a `from_hyp` method.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn mock(method: Method, uri: &str) -> Request {
|
pub fn mock(method: Method, uri: &str) -> Request {
|
||||||
Request {
|
Request {
|
||||||
|
@ -106,7 +109,7 @@ impl Request {
|
||||||
method: method,
|
method: method,
|
||||||
cookies: Cookies::new(&[]),
|
cookies: Cookies::new(&[]),
|
||||||
uri: URIBuf::from(uri),
|
uri: URIBuf::from(uri),
|
||||||
headers: header::Headers::new(),
|
headers: HeaderMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,8 +123,7 @@ impl Request {
|
||||||
///
|
///
|
||||||
/// Returns the headers in this request.
|
/// Returns the headers in this request.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn headers(&self) -> &header::Headers {
|
pub fn headers(&self) -> &HeaderMap {
|
||||||
// FIXME: Get rid of Hyper.
|
|
||||||
&self.headers
|
&self.headers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,29 +141,9 @@ impl Request {
|
||||||
/// Content-Type of [any](struct.ContentType.html#method.any) is returned.
|
/// Content-Type of [any](struct.ContentType.html#method.any) is returned.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn content_type(&self) -> ContentType {
|
pub fn content_type(&self) -> ContentType {
|
||||||
let hyp_ct = self.headers().get::<header::ContentType>();
|
self.headers().get_one("Content-Type")
|
||||||
hyp_ct.map_or(ContentType::Any, |ct| ContentType::from(&ct.0))
|
.and_then(|value| value.parse().ok())
|
||||||
}
|
.unwrap_or(ContentType::Any)
|
||||||
|
|
||||||
/// <div class="stability" style="margin-left: 0;">
|
|
||||||
/// <em class="stab unstable">
|
|
||||||
/// Unstable
|
|
||||||
/// (<a href="https://github.com/SergioBenitez/Rocket/issues/17">#17</a>):
|
|
||||||
/// The underlying HTTP library/types are likely to change before v1.0.
|
|
||||||
/// </em>
|
|
||||||
/// </div>
|
|
||||||
///
|
|
||||||
/// Returns the first content-type accepted by this request.
|
|
||||||
pub fn accepts(&self) -> ContentType {
|
|
||||||
let accept = self.headers().get::<header::Accept>();
|
|
||||||
accept.map_or(ContentType::Any, |accept| {
|
|
||||||
let items = &accept.0;
|
|
||||||
if items.len() < 1 {
|
|
||||||
return ContentType::Any;
|
|
||||||
} else {
|
|
||||||
return ContentType::from(items[0].item.clone());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the URI from the request. Rocket only allows absolute URIs, so
|
/// Retrieves the URI from the request. Rocket only allows absolute URIs, so
|
||||||
|
@ -179,7 +161,9 @@ impl Request {
|
||||||
// in this structure, which is (obviously) guaranteed to live as long as
|
// in this structure, which is (obviously) guaranteed to live as long as
|
||||||
// the structure AS LONG AS it is not moved out or changed. AS A RESULT,
|
// the structure AS LONG AS it is not moved out or changed. AS A RESULT,
|
||||||
// the `uri` fields MUST NEVER be changed once it is set.
|
// the `uri` fields MUST NEVER be changed once it is set.
|
||||||
// TODO: Find a way to enforce these. Look at OwningRef for inspiration.
|
//
|
||||||
|
// TODO: Find a way to ecapsulate this better. Look at OwningRef/Rental
|
||||||
|
// for inspiration.
|
||||||
use ::std::mem::transmute;
|
use ::std::mem::transmute;
|
||||||
*self.params.borrow_mut() = unsafe {
|
*self.params.borrow_mut() = unsafe {
|
||||||
transmute(route.get_params(self.uri.as_uri()))
|
transmute(route.get_params(self.uri.as_uri()))
|
||||||
|
@ -188,20 +172,13 @@ impl Request {
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_headers(&mut self, h_headers: header::Headers) {
|
pub fn add_header(&mut self, header: Header<'static>) {
|
||||||
let cookies = match h_headers.get::<header::Cookie>() {
|
self.headers.add(header);
|
||||||
// TODO: Retrieve key from config.
|
|
||||||
Some(cookie) => cookie.to_cookie_jar(&[]),
|
|
||||||
None => Cookies::new(&[]),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.headers = h_headers;
|
|
||||||
self.cookies = cookies;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn new(h_method: hyper::Method,
|
pub fn new(h_method: hyper::Method,
|
||||||
h_headers: header::Headers,
|
h_headers: hyper::header::Headers,
|
||||||
h_uri: hyper::RequestUri)
|
h_uri: hyper::RequestUri)
|
||||||
-> Result<Request, String> {
|
-> Result<Request, String> {
|
||||||
let uri = match h_uri {
|
let uri = match h_uri {
|
||||||
|
@ -214,18 +191,23 @@ impl Request {
|
||||||
_ => return Err(format!("Bad method: {}", h_method)),
|
_ => return Err(format!("Bad method: {}", h_method)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let cookies = match h_headers.get::<header::Cookie>() {
|
let cookies = match h_headers.get::<hyper::header::Cookie>() {
|
||||||
// TODO: Retrieve key from config.
|
// TODO: Retrieve key from config.
|
||||||
Some(cookie) => cookie.to_cookie_jar(&[]),
|
Some(cookie) => cookie.to_cookie_jar(&[]),
|
||||||
None => Cookies::new(&[]),
|
None => Cookies::new(&[]),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut headers = HeaderMap::new();
|
||||||
|
for h_header in h_headers.iter() {
|
||||||
|
headers.add_raw(h_header.name().to_string(), h_header.value_string())
|
||||||
|
}
|
||||||
|
|
||||||
let request = Request {
|
let request = Request {
|
||||||
params: RefCell::new(vec![]),
|
params: RefCell::new(vec![]),
|
||||||
method: method,
|
method: method,
|
||||||
cookies: cookies,
|
cookies: cookies,
|
||||||
uri: uri,
|
uri: uri,
|
||||||
headers: h_headers,
|
headers: headers,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(request)
|
Ok(request)
|
||||||
|
|
|
@ -282,9 +282,9 @@ impl<'r> Response<'r> {
|
||||||
self.body = Some(Body::Chunked(Box::new(body), chunk_size));
|
self.body = Some(Body::Chunked(Box::new(body), chunk_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replaces this response's status and body with that of `other`, if they
|
/// Replaces this response's status and body with that of `other`, if they
|
||||||
// exist. Any headers that exist in `other` replace the ones in `self`. Any
|
/// exist in `other`. Any headers that exist in `other` replace the ones in
|
||||||
// in `self` that aren't in `other` remain.
|
/// `self`. Any in `self` that aren't in `other` remain in `self`.
|
||||||
pub fn merge(&mut self, other: Response<'r>) {
|
pub fn merge(&mut self, other: Response<'r>) {
|
||||||
if let Some(status) = other.status {
|
if let Some(status) = other.status {
|
||||||
self.status = Some(status);
|
self.status = Some(status);
|
||||||
|
@ -294,7 +294,7 @@ impl<'r> Response<'r> {
|
||||||
self.body = Some(body);
|
self.body = Some(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, values) in other.headers.into_iter() {
|
for (name, values) in other.headers.into_iter_raw() {
|
||||||
self.headers.replace_all(name, values);
|
self.headers.replace_all(name, values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -311,7 +311,7 @@ impl<'r> Response<'r> {
|
||||||
self.body = other.body;
|
self.body = other.body;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, mut values) in other.headers.into_iter() {
|
for (name, mut values) in other.headers.into_iter_raw() {
|
||||||
self.headers.add_all(name, &mut values);
|
self.headers.add_all(name, &mut values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,9 +53,10 @@
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! # use rocket::http::Method::*;
|
//! # use rocket::http::Method::*;
|
||||||
//! # use rocket::testing::MockRequest;
|
//! # use rocket::testing::MockRequest;
|
||||||
|
//! # use rocket::http::ContentType;
|
||||||
//! let (username, password, age) = ("user", "password", 32);
|
//! let (username, password, age) = ("user", "password", 32);
|
||||||
//! MockRequest::new(Post, "/login")
|
//! MockRequest::new(Post, "/login")
|
||||||
//! .headers(&[("Content-Type", "application/x-www-form-urlencoded")])
|
//! .header(ContentType::Form)
|
||||||
//! .body(&format!("username={}&password={}&age={}", username, password, age));
|
//! .body(&format!("username={}&password={}&age={}", username, password, age));
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
@ -99,8 +100,8 @@
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use http::{hyper, Method};
|
use http::{Method, Header, Cookie};
|
||||||
use {Rocket, Request, Data};
|
use ::{Rocket, Request, Data};
|
||||||
|
|
||||||
/// A type for mocking requests for testing Rocket applications.
|
/// A type for mocking requests for testing Rocket applications.
|
||||||
pub struct MockRequest {
|
pub struct MockRequest {
|
||||||
|
@ -110,6 +111,7 @@ pub struct MockRequest {
|
||||||
|
|
||||||
impl MockRequest {
|
impl MockRequest {
|
||||||
/// Constructs a new mocked request with the given `method` and `uri`.
|
/// Constructs a new mocked request with the given `method` and `uri`.
|
||||||
|
#[inline]
|
||||||
pub fn new<S: AsRef<str>>(method: Method, uri: S) -> Self {
|
pub fn new<S: AsRef<str>>(method: Method, uri: S) -> Self {
|
||||||
MockRequest {
|
MockRequest {
|
||||||
request: Request::mock(method, uri.as_ref()),
|
request: Request::mock(method, uri.as_ref()),
|
||||||
|
@ -117,33 +119,42 @@ impl MockRequest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the headers for this request.
|
/// Add a header to this request.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Set the Content-Type header:
|
/// Add the Content-Type header:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use rocket::http::Method::*;
|
/// use rocket::http::Method::*;
|
||||||
/// use rocket::testing::MockRequest;
|
/// use rocket::testing::MockRequest;
|
||||||
|
/// use rocket::http::ContentType;
|
||||||
///
|
///
|
||||||
/// let req = MockRequest::new(Get, "/").headers(&[
|
/// let req = MockRequest::new(Get, "/").header(ContentType::JSON);
|
||||||
/// ("Content-Type", "application/json")
|
|
||||||
/// ]);
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn headers<'h, H: AsRef<[(&'h str, &'h str)]>>(mut self, headers: H) -> Self {
|
#[inline]
|
||||||
let mut hyp_headers = hyper::header::Headers::new();
|
pub fn header<'h, H: Into<Header<'static>>>(mut self, header: H) -> Self {
|
||||||
|
self.request.add_header(header.into());
|
||||||
for &(name, fields) in headers.as_ref() {
|
self
|
||||||
let mut vec_fields = vec![];
|
}
|
||||||
for field in fields.split(";") {
|
///
|
||||||
vec_fields.push(field.as_bytes().to_vec());
|
/// Add a cookie to this request.
|
||||||
}
|
///
|
||||||
|
/// # Examples
|
||||||
hyp_headers.set_raw(name.to_string(), vec_fields);
|
///
|
||||||
}
|
/// Add `user_id` cookie:
|
||||||
|
///
|
||||||
self.request.set_headers(hyp_headers);
|
/// ```rust
|
||||||
|
/// use rocket::http::Method::*;
|
||||||
|
/// use rocket::testing::MockRequest;
|
||||||
|
/// use rocket::http::Cookie;
|
||||||
|
///
|
||||||
|
/// let req = MockRequest::new(Get, "/")
|
||||||
|
/// .cookie(Cookie::new("user_id".into(), "12".into()));
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn cookie(self, cookie: Cookie) -> Self {
|
||||||
|
self.request.cookies().add(cookie);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,16 +167,13 @@ impl MockRequest {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use rocket::http::Method::*;
|
/// use rocket::http::Method::*;
|
||||||
/// use rocket::testing::MockRequest;
|
/// use rocket::testing::MockRequest;
|
||||||
|
/// use rocket::http::ContentType;
|
||||||
///
|
///
|
||||||
/// let req = MockRequest::new(Post, "/").headers(&[
|
/// let req = MockRequest::new(Post, "/")
|
||||||
/// ("Content-Type", "application/json")
|
/// .header(ContentType::JSON)
|
||||||
/// ]).body(r#"
|
/// .body(r#"{ "key": "value", "array": [1, 2, 3], }"#);
|
||||||
/// {
|
|
||||||
/// "key": "value",
|
|
||||||
/// "array": [1, 2, 3],
|
|
||||||
/// }
|
|
||||||
/// "#);
|
|
||||||
/// ```
|
/// ```
|
||||||
|
#[inline]
|
||||||
pub fn body<S: AsRef<str>>(mut self, body: S) -> Self {
|
pub fn body<S: AsRef<str>>(mut self, body: S) -> Self {
|
||||||
self.data = Data::new(body.as_ref().as_bytes().into());
|
self.data = Data::new(body.as_ref().as_bytes().into());
|
||||||
self
|
self
|
||||||
|
|
Loading…
Reference in New Issue