Skip to content

Commit

Permalink
Add 'LocalRequest::private_cookie()'.
Browse files Browse the repository at this point in the history
Resolves #368.
  • Loading branch information
ivstas authored and SergioBenitez committed Dec 29, 2017
1 parent dd07c36 commit 70413b1
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 14 deletions.
2 changes: 1 addition & 1 deletion lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ isatty = "0.1"

[dependencies.cookie]
git = "https://github.com/alexcrichton/cookie-rs"
rev = "b8298e"
rev = "f4e6930"
features = ["percent-encode", "secure"]

[dev-dependencies]
Expand Down
46 changes: 33 additions & 13 deletions lib/src/http/cookies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,23 +231,43 @@ impl<'a> Cookies<'a> {
/// ```
pub fn add_private(&mut self, mut cookie: Cookie<'static>) {
if let Cookies::Jarred(ref mut jar, key) = *self {
if cookie.path().is_none() {
cookie.set_path("/");
}
Cookies::set_private_defaults(&mut cookie);
jar.private(key).add(cookie)
}
}

if cookie.http_only().is_none() {
cookie.set_http_only(true);
}
/// Adds an original, private `cookie` to the collection.
pub(crate) fn add_original_private(&mut self, mut cookie: Cookie<'static>) {
if let Cookies::Jarred(ref mut jar, key) = *self {
Cookies::set_private_defaults(&mut cookie);
jar.private(key).add_original(cookie)
}
}

if cookie.expires().is_none() {
cookie.set_expires(::time::now() + ::time::Duration::weeks(1));
}
/// For each property mentioned below, this method checks
/// if there is provided value and if there is none, set default value.
/// Default values are:
///
/// * `path`: `"/"`
/// * `SameSite`: `Strict`
/// * `HttpOnly`: `true`
/// * `Expires`: 1 week from now
///
fn set_private_defaults(cookie: &mut Cookie<'static>) {
if cookie.path().is_none() {
cookie.set_path("/");
}

if cookie.same_site().is_none() {
cookie.set_same_site(SameSite::Strict);
}
if cookie.http_only().is_none() {
cookie.set_http_only(true);
}

jar.private(key).add(cookie)
if cookie.expires().is_none() {
cookie.set_expires(::time::now() + ::time::Duration::weeks(1));
}

if cookie.same_site().is_none() {
cookie.set_same_site(SameSite::Strict);
}
}

Expand Down
22 changes: 22 additions & 0 deletions lib/src/local/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,28 @@ impl<'c> LocalRequest<'c> {
self
}

/// Add a [private cookie] to this request.
///
/// [private cookie]: /rocket/http/enum.Cookies.html#private-cookies
///
/// # Examples
///
/// Add `user_id` as a private cookie:
///
/// ```rust
/// use rocket::local::Client;
/// use rocket::http::Cookie;
///
/// let client = Client::new(rocket::ignite()).unwrap();
/// # #[allow(unused_variables)]
/// let req = client.get("/").private_cookie(Cookie::new("user_id", "sb"));
/// ```
#[inline]
pub fn private_cookie(self, cookie: Cookie<'static>) -> Self {
self.request.cookies().add_original_private(cookie);
self
}

// TODO: For CGI, we want to be able to set the body to be stdin without
// actually reading everything into a vector. Can we allow that here while
// keeping the simplicity? Looks like it would require us to reintroduce a
Expand Down
44 changes: 44 additions & 0 deletions lib/tests/local_request_private_cookie-issue-368.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#![feature(plugin, decl_macro)]
#![plugin(rocket_codegen)]

extern crate rocket;

use rocket::http::Cookies;

#[get("/")]
fn return_private_cookie(mut cookies: Cookies) -> Option<String> {
match cookies.get_private("cookie_name") {
Some(cookie) => Some(cookie.value().into()),
None => None,
}
}

mod tests {
use super::*;
use rocket::local::Client;
use rocket::http::Cookie;
use rocket::http::Status;

#[test]
fn private_cookie_is_returned() {
let rocket = rocket::ignite().mount("/", routes![return_private_cookie]);

let client = Client::new(rocket).unwrap();
let req = client.get("/").private_cookie(Cookie::new("cookie_name", "cookie_value"));
let mut response = req.dispatch();

assert_eq!(response.body_string(), Some("cookie_value".into()));
assert_eq!(response.headers().get_one("Set-Cookie"), None);
}

#[test]
fn regular_cookie_is_not_returned() {
let rocket = rocket::ignite().mount("/", routes![return_private_cookie]);

let client = Client::new(rocket).unwrap();
let req = client.get("/").cookie(Cookie::new("cookie_name", "cookie_value"));
let response = req.dispatch();

assert_eq!(response.status(), Status::NotFound);
}
}

0 comments on commit 70413b1

Please sign in to comment.