mirror of https://github.com/rwf2/Rocket.git
Remove 'CookieJar::get_private_pending()'.
This commit removes the 'CookieJar::get_private_pending()' method in favor of the already existing and correct 'CookieJar::get_pending()' method. Previously, the 'CookieJar::get_private_pending()' method attempted to decrypt the value of a pending cookie, which in reality is plaintext, thus failing. Because the pending value is plaintext, the 'CookieJar::get_pending()' method suffices. Documentation has been updated to refer to 'CookieJar::get_pending()'. Fixes #2063.
This commit is contained in:
parent
442b668a7a
commit
1ba41b3990
|
@ -39,7 +39,7 @@ pear = "0.2.3"
|
|||
pin-project-lite = "0.2"
|
||||
memchr = "2"
|
||||
stable-pattern = "0.1"
|
||||
cookie = { version = "0.16.0", features = ["secure", "percent-encode"] }
|
||||
cookie = { version = "0.16.0", features = ["percent-encode", "secure"] }
|
||||
state = "0.5.1"
|
||||
|
||||
[dependencies.x509-parser]
|
||||
|
|
|
@ -19,9 +19,8 @@ pub use self::cookie::{Cookie, SameSite, Iter};
|
|||
/// Changes to a `CookieJar` are _not_ visible via the normal [`get()`] and
|
||||
/// [`get_private()`] methods. This is typically the desired effect as a
|
||||
/// `CookieJar` always reflects the cookies in an incoming request. In cases
|
||||
/// where this is not desired, the [`get_pending()`] and
|
||||
/// [`get_private_pending()`] methods are available, which always return the
|
||||
/// latest changes.
|
||||
/// where this is not desired, the [`get_pending()`] method is available, which
|
||||
/// always returns the latest changes.
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate rocket;
|
||||
|
@ -61,16 +60,14 @@ pub use self::cookie::{Cookie, SameSite, Iter};
|
|||
/// A type of `&CookieJar` can be retrieved via its `FromRequest` implementation
|
||||
/// as a request guard or via the [`Request::cookies()`] method. Individual
|
||||
/// cookies can be retrieved via the [`get()`] and [`get_private()`] methods.
|
||||
/// Pending changes can be observed via the [`get_pending()`] and
|
||||
/// [`get_private_pending()`] methods. Cookies can be added or removed via the
|
||||
/// [`add()`], [`add_private()`], [`remove()`], and [`remove_private()`]
|
||||
/// methods.
|
||||
/// Pending changes can be observed via the [`get_pending()`] method. Cookies
|
||||
/// can be added or removed via the [`add()`], [`add_private()`], [`remove()`],
|
||||
/// and [`remove_private()`] methods.
|
||||
///
|
||||
/// [`Request::cookies()`]: crate::Request::cookies()
|
||||
/// [`get()`]: #method.get
|
||||
/// [`get_private()`]: #method.get_private
|
||||
/// [`get_pending()`]: #method.get_pending
|
||||
/// [`get_private_pending()`]: #method.get_private_pending
|
||||
/// [`add()`]: #method.add
|
||||
/// [`add_private()`]: #method.add_private
|
||||
/// [`remove()`]: #method.remove
|
||||
|
@ -223,7 +220,7 @@ impl<'a> CookieJar<'a> {
|
|||
///
|
||||
/// **Note:** This method _does not_ obverse changes made via additions and
|
||||
/// removals to the cookie jar. To observe those changes, use
|
||||
/// [`CookieJar::get_private_pending()`].
|
||||
/// [`CookieJar::get_pending()`].
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
@ -243,8 +240,12 @@ impl<'a> CookieJar<'a> {
|
|||
}
|
||||
|
||||
/// Returns a reference to the _original or pending_ `Cookie` inside this
|
||||
/// container with the name `name`. If no such cookie exists, returns
|
||||
/// `None`.
|
||||
/// container with the name `name`, irrespective of whether the cookie was
|
||||
/// private or not. If no such cookie exists, returns `None`.
|
||||
///
|
||||
/// This _does not_ return cookies sent by the client in a request. To
|
||||
/// retrieve usch cookies, using [`CookieJar::get()`] or
|
||||
/// [`CookieJar::get_private()`].
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
@ -270,29 +271,6 @@ impl<'a> CookieJar<'a> {
|
|||
self.get(name).cloned()
|
||||
}
|
||||
|
||||
/// Retrives the _original or pending_ `Cookie` inside this collection with
|
||||
/// the name `name` and authenticates and decrypts the cookie's value. If
|
||||
/// the cookie cannot be found, or the cookie fails to authenticate or
|
||||
/// decrypt, `None` is returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate rocket;
|
||||
/// use rocket::http::{Cookie, CookieJar};
|
||||
///
|
||||
/// #[get("/")]
|
||||
/// fn handler(jar: &CookieJar<'_>) {
|
||||
/// let pending_cookie = jar.get_private_pending("name");
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(feature = "secrets")]
|
||||
#[cfg_attr(nightly, doc(cfg(feature = "secrets")))]
|
||||
pub fn get_private_pending(&self, name: &str) -> Option<Cookie<'static>> {
|
||||
let cookie = self.get_pending(name)?;
|
||||
self.jar.private(&self.config.secret_key.key).decrypt(cookie)
|
||||
}
|
||||
|
||||
/// Adds `cookie` to this collection.
|
||||
///
|
||||
/// Unless a value is set for the given property, the following defaults are
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
#![cfg(feature = "secrets")]
|
||||
#![deny(warnings)]
|
||||
|
||||
use rocket::http::{Cookie, CookieJar, SameSite};
|
||||
use rocket::{get, post, routes};
|
||||
|
||||
#[post("/")]
|
||||
fn cookie_add_private(jar: &CookieJar<'_>) {
|
||||
let mut cookie_a = Cookie::new("a", "v1");
|
||||
jar.add(cookie_a.clone());
|
||||
let mut cookie_b = Cookie::new("b", "v2");
|
||||
jar.add_private(cookie_b.clone());
|
||||
jar.add(Cookie::new("c", "v3"));
|
||||
|
||||
// private: CookieJar::set_defaults(&mut cookie_a);
|
||||
cookie_a.set_path("/");
|
||||
cookie_a.set_same_site(SameSite::Strict);
|
||||
assert_eq!(jar.get_pending(cookie_a.name()), Some(cookie_a));
|
||||
|
||||
// private: CookieJar::set_private_defaults(&mut cookie_b);
|
||||
cookie_b.set_path("/");
|
||||
cookie_b.set_same_site(SameSite::Strict);
|
||||
cookie_b.set_http_only(true);
|
||||
let expires = time::OffsetDateTime::now_utc() + time::Duration::weeks(1);
|
||||
cookie_b.set_expires(expires);
|
||||
let mut cookie_b_pending = jar
|
||||
.get_pending(cookie_b.name())
|
||||
.expect("cookie_b_pending None");
|
||||
cookie_b_pending.set_expires(expires);
|
||||
assert_eq!(cookie_b_pending, cookie_b);
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
fn cookie_get_private(jar: &CookieJar<'_>) -> String {
|
||||
let (a, b, c) = (jar.get("a"), jar.get_private("b"), jar.get("c"));
|
||||
assert_ne!(a, b.as_ref());
|
||||
assert_ne!(a, c);
|
||||
assert_ne!(b.as_ref(), c);
|
||||
|
||||
format!(
|
||||
"{}{}{}",
|
||||
a.unwrap().value(),
|
||||
b.unwrap().value(),
|
||||
c.unwrap().value()
|
||||
)
|
||||
}
|
||||
|
||||
/// For test if we got really a private cookie
|
||||
#[get("/oh-no")]
|
||||
fn cookie_get(jar: &CookieJar<'_>) -> String {
|
||||
let (a, b, c) = (jar.get("a"), jar.get("b"), jar.get("c"));
|
||||
|
||||
format!(
|
||||
"{}{}{}",
|
||||
a.unwrap().value(),
|
||||
b.unwrap().value(),
|
||||
c.unwrap().value()
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod cookies_private_tests {
|
||||
use super::*;
|
||||
use rocket::local::blocking::Client;
|
||||
use rocket::{Build, Rocket};
|
||||
|
||||
fn rocket() -> Rocket<Build> {
|
||||
rocket::build().mount(
|
||||
"/",
|
||||
routes![cookie_add_private, cookie_get, cookie_get_private],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cookie_add_private() {
|
||||
let client = Client::debug(rocket()).unwrap();
|
||||
let response = client.post("/").dispatch();
|
||||
let cookies = response.cookies();
|
||||
assert_eq!(cookies.iter().count(), 3);
|
||||
assert_eq!(cookies.get("a").unwrap().value(), "v1");
|
||||
assert_eq!(cookies.get_private("b").unwrap().value(), "v2");
|
||||
assert_ne!(cookies.get("b").unwrap().value(), "v2");
|
||||
assert_eq!(cookies.get("c").unwrap().value(), "v3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cookie_get_private() {
|
||||
let client = Client::debug(rocket()).unwrap();
|
||||
let response = client
|
||||
.get("/")
|
||||
.cookie(Cookie::new("a", "Cookie"))
|
||||
.private_cookie(Cookie::new("b", " tastes "))
|
||||
.cookie(Cookie::new("c", "good!"))
|
||||
.dispatch();
|
||||
|
||||
assert_eq!(response.into_string().unwrap(), "Cookie tastes good!");
|
||||
}
|
||||
|
||||
/// Test if we got really a private cookie
|
||||
#[test]
|
||||
fn test_cookie_get_ohno() {
|
||||
let client = Client::debug(rocket()).unwrap();
|
||||
let response = client
|
||||
.get("/oh-no")
|
||||
.cookie(Cookie::new("a", "Cookie"))
|
||||
.private_cookie(Cookie::new("b", " tastes "))
|
||||
.cookie(Cookie::new("c", "good!"))
|
||||
.dispatch();
|
||||
|
||||
assert_ne!(response.into_string().unwrap(), "Cookie tastes good!");
|
||||
}
|
||||
}
|
|
@ -531,9 +531,9 @@ rocket = { version = "0.5.0-rc.1", features = ["secrets"] }
|
|||
```
|
||||
|
||||
The API for retrieving, adding, and removing private cookies is identical except
|
||||
methods are suffixed with `_private`. These methods are: [`get_private`],
|
||||
[`get_private_pending`], [`add_private`], and [`remove_private`]. An example of
|
||||
their usage is below:
|
||||
that most methods are suffixed with `_private`. These methods are:
|
||||
[`get_private`], [`get_pending`], [`add_private`], and [`remove_private`]. An
|
||||
example of their usage is below:
|
||||
|
||||
```rust
|
||||
# #[macro_use] extern crate rocket;
|
||||
|
@ -576,7 +576,6 @@ For more information on configuration, see the [Configuration](../configuration)
|
|||
section of the guide.
|
||||
|
||||
[`get_private`]: @api/rocket/http/struct.CookieJar.html#method.get_private
|
||||
[`get_private_pending`]: @api/rocket/http/struct.CookieJar.html#method.get_private_pending
|
||||
[`add_private`]: @api/rocket/http/struct.CookieJar.html#method.add_private
|
||||
[`remove_private`]: @api/rocket/http/struct.CookieJar.html#method.remove_private
|
||||
|
||||
|
|
Loading…
Reference in New Issue