mirror of
https://github.com/rwf2/Rocket.git
synced 2025-02-06 16:52:03 +00:00
Update to cookie 0.7. Use 256-bit session_keys.
This commit involves several breaking changes: * `session_key` config param must be a 256-bit base64 encoded string. * `FromRequest` is implemented for `Cookies`, not `Cookie`. * Only a single `Cookies` instance can be retrieved at a time. * `Config::take_session_key` returns a `Vec<u8>`. * `Into<Header>` is implemented for `&Cookie`, not `Cookie`.
This commit is contained in:
parent
6be902162d
commit
722ee93f8b
@ -16,7 +16,7 @@ struct User<'a> {
|
|||||||
fn get<'r>(name: &str,
|
fn get<'r>(name: &str,
|
||||||
query: User<'r>,
|
query: User<'r>,
|
||||||
user: Form<'r, User<'r>>,
|
user: Form<'r, User<'r>>,
|
||||||
cookies: &Cookies)
|
cookies: Cookies)
|
||||||
-> &'static str {
|
-> &'static str {
|
||||||
"hi"
|
"hi"
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ port = 80
|
|||||||
log = "normal"
|
log = "normal"
|
||||||
workers = 8
|
workers = 8
|
||||||
# don't use this key! generate your own and keep it private!
|
# don't use this key! generate your own and keep it private!
|
||||||
session_key = "VheMwXIBygSmOlZAhuWl2B+zgvTN3WW5"
|
session_key = "8Xui8SN4mI+7egV/9dlfYYLGQJeEx4+DwmSQLwDVXJg="
|
||||||
|
|
||||||
[production]
|
[production]
|
||||||
address = "0.0.0.0"
|
address = "0.0.0.0"
|
||||||
@ -23,4 +23,4 @@ port = 80
|
|||||||
workers = 12
|
workers = 12
|
||||||
log = "critical"
|
log = "critical"
|
||||||
# don't use this key! generate your own and keep it private!
|
# don't use this key! generate your own and keep it private!
|
||||||
session_key = "adL5fFIPmZBrlyHk2YT4NLV3YCk2gFXz"
|
session_key = "hPRYyVRiMyxpw5sBB1XeCMN1kFsDCqKvBi2QJxBVHQk="
|
||||||
|
@ -20,14 +20,14 @@ struct Message {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[post("/submit", data = "<message>")]
|
#[post("/submit", data = "<message>")]
|
||||||
fn submit(cookies: &Cookies, message: Form<Message>) -> Redirect {
|
fn submit(mut cookies: Cookies, message: Form<Message>) -> Redirect {
|
||||||
cookies.add(Cookie::new("message", message.into_inner().message));
|
cookies.add(Cookie::new("message", message.into_inner().message));
|
||||||
Redirect::to("/")
|
Redirect::to("/")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
fn index(cookies: &Cookies) -> Template {
|
fn index(cookies: Cookies) -> Template {
|
||||||
let cookie = cookies.find("message");
|
let cookie = cookies.get("message");
|
||||||
let mut context = HashMap::new();
|
let mut context = HashMap::new();
|
||||||
if let Some(ref cookie) = cookie {
|
if let Some(ref cookie) = cookie {
|
||||||
context.insert("message", cookie.value());
|
context.insert("message", cookie.value());
|
||||||
|
@ -25,10 +25,13 @@ state = "^0.2"
|
|||||||
time = "^0.1"
|
time = "^0.1"
|
||||||
memchr = "1"
|
memchr = "1"
|
||||||
|
|
||||||
|
# FIXME: session support should be optional
|
||||||
|
base64 = "0.4"
|
||||||
|
|
||||||
|
# FIXME: session support should be optional
|
||||||
[dependencies.cookie]
|
[dependencies.cookie]
|
||||||
version = "^0.6"
|
version = "^0.7"
|
||||||
default-features = false
|
features = ["percent-encode", "secure"]
|
||||||
features = ["percent-encode"]
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
lazy_static = "0.2"
|
lazy_static = "0.2"
|
||||||
|
@ -152,12 +152,12 @@ impl ConfigBuilder {
|
|||||||
/// use rocket::LoggingLevel;
|
/// use rocket::LoggingLevel;
|
||||||
/// use rocket::config::{Config, Environment};
|
/// use rocket::config::{Config, Environment};
|
||||||
///
|
///
|
||||||
/// let key = "VheMwXIBygSmOlZAhuWl2B+zgvTN3WW5";
|
/// let key = "8Xui8SN4mI+7egV/9dlfYYLGQJeEx4+DwmSQLwDVXJg=";
|
||||||
/// let mut config = Config::build(Environment::Staging)
|
/// let mut config = Config::build(Environment::Staging)
|
||||||
/// .session_key(key)
|
/// .session_key(key)
|
||||||
/// .unwrap();
|
/// .unwrap();
|
||||||
///
|
///
|
||||||
/// assert_eq!(config.take_session_key(), Some(key.to_string()));
|
/// assert!(config.take_session_key().is_some());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn session_key<K: Into<String>>(mut self, key: K) -> Self {
|
pub fn session_key<K: Into<String>>(mut self, key: K) -> Self {
|
||||||
self.session_key = Some(key.into());
|
self.session_key = Some(key.into());
|
||||||
|
@ -9,7 +9,7 @@ use std::env;
|
|||||||
use config::Environment::*;
|
use config::Environment::*;
|
||||||
use config::{self, Value, ConfigBuilder, Environment, ConfigError};
|
use config::{self, Value, ConfigBuilder, Environment, ConfigError};
|
||||||
|
|
||||||
use num_cpus;
|
use {num_cpus, base64};
|
||||||
use logger::LoggingLevel;
|
use logger::LoggingLevel;
|
||||||
|
|
||||||
/// Structure for Rocket application configuration.
|
/// Structure for Rocket application configuration.
|
||||||
@ -44,7 +44,7 @@ pub struct Config {
|
|||||||
/// The path to the configuration file this config belongs to.
|
/// The path to the configuration file this config belongs to.
|
||||||
pub config_path: PathBuf,
|
pub config_path: PathBuf,
|
||||||
/// The session key.
|
/// The session key.
|
||||||
session_key: RwLock<Option<String>>,
|
session_key: RwLock<Option<Vec<u8>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! parse {
|
macro_rules! parse {
|
||||||
@ -175,12 +175,6 @@ impl Config {
|
|||||||
ConfigError::BadType(id, expect, actual, self.config_path.clone())
|
ConfigError::BadType(id, expect, actual, self.config_path.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aliases to `set` before the method is removed.
|
|
||||||
pub(crate) fn set_raw(&mut self, name: &str, val: &Value) -> config::Result<()> {
|
|
||||||
#[allow(deprecated)]
|
|
||||||
self.set(name, val)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the configuration `val` for the `name` entry. If the `name` is one
|
/// Sets the configuration `val` for the `name` entry. If the `name` is one
|
||||||
/// of "address", "port", "session_key", "log", or "workers" (the "default"
|
/// of "address", "port", "session_key", "log", or "workers" (the "default"
|
||||||
/// values), the appropriate value in the `self` Config structure is set.
|
/// values), the appropriate value in the `self` Config structure is set.
|
||||||
@ -195,8 +189,7 @@ impl Config {
|
|||||||
/// * **workers**: Integer (16-bit unsigned)
|
/// * **workers**: Integer (16-bit unsigned)
|
||||||
/// * **log**: String
|
/// * **log**: String
|
||||||
/// * **session_key**: String (192-bit base64)
|
/// * **session_key**: String (192-bit base64)
|
||||||
#[deprecated(since="0.2", note="use the set_{param} methods instead")]
|
pub(crate) fn set_raw(&mut self, name: &str, val: &Value) -> config::Result<()> {
|
||||||
pub fn set(&mut self, name: &str, val: &Value) -> config::Result<()> {
|
|
||||||
if name == "address" {
|
if name == "address" {
|
||||||
let address_str = parse!(self, name, val, as_str, "a string")?;
|
let address_str = parse!(self, name, val, as_str, "a string")?;
|
||||||
self.set_address(address_str)?;
|
self.set_address(address_str)?;
|
||||||
@ -335,20 +328,27 @@ impl Config {
|
|||||||
/// # use rocket::config::ConfigError;
|
/// # use rocket::config::ConfigError;
|
||||||
/// # fn config_test() -> Result<(), ConfigError> {
|
/// # fn config_test() -> Result<(), ConfigError> {
|
||||||
/// let mut config = Config::new(Environment::Staging)?;
|
/// let mut config = Config::new(Environment::Staging)?;
|
||||||
/// assert!(config.set_session_key("VheMwXIBygSmOlZAhuWl2B+zgvTN3WW5").is_ok());
|
/// let key = "8Xui8SN4mI+7egV/9dlfYYLGQJeEx4+DwmSQLwDVXJg=";
|
||||||
|
/// assert!(config.set_session_key(key).is_ok());
|
||||||
/// assert!(config.set_session_key("hello? anyone there?").is_err());
|
/// assert!(config.set_session_key("hello? anyone there?").is_err());
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set_session_key<K: Into<String>>(&mut self, key: K) -> config::Result<()> {
|
pub fn set_session_key<K: Into<String>>(&mut self, key: K) -> config::Result<()> {
|
||||||
let key = key.into();
|
let key = key.into();
|
||||||
if key.len() != 32 {
|
let error = self.bad_type("session_key", "string",
|
||||||
return Err(self.bad_type("session_key",
|
"a 256-bit base64 encoded string");
|
||||||
"string",
|
|
||||||
"a 192-bit base64 string"));
|
if key.len() != 44 {
|
||||||
|
return Err(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.session_key = RwLock::new(Some(key));
|
let bytes = match base64::decode(&key) {
|
||||||
|
Ok(bytes) => bytes,
|
||||||
|
Err(_) => return Err(error)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.session_key = RwLock::new(Some(bytes));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,21 +435,21 @@ impl Config {
|
|||||||
/// use rocket::config::{Config, Environment};
|
/// use rocket::config::{Config, Environment};
|
||||||
///
|
///
|
||||||
/// // Create a new config with a session key.
|
/// // Create a new config with a session key.
|
||||||
/// let key = "adL5fFIPmZBrlyHk2YT4NLV3YCk2gFXz";
|
/// let key = "8Xui8SN4mI+7egV/9dlfYYLGQJeEx4+DwmSQLwDVXJg=";
|
||||||
/// let config = Config::build(Environment::Staging)
|
/// let config = Config::build(Environment::Staging)
|
||||||
/// .session_key(key)
|
/// .session_key(key)
|
||||||
/// .unwrap();
|
/// .unwrap();
|
||||||
///
|
///
|
||||||
/// // Get the key for the first time.
|
/// // Get the key for the first time.
|
||||||
/// let session_key = config.take_session_key();
|
/// let session_key = config.take_session_key();
|
||||||
/// assert_eq!(session_key, Some(key.to_string()));
|
/// assert!(session_key.is_some());
|
||||||
///
|
///
|
||||||
/// // Try to get the key again.
|
/// // Try to get the key again.
|
||||||
/// let session_key_again = config.take_session_key();
|
/// let session_key_again = config.take_session_key();
|
||||||
/// assert_eq!(session_key_again, None);
|
/// assert_eq!(session_key_again, None);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn take_session_key(&self) -> Option<String> {
|
pub fn take_session_key(&self) -> Option<Vec<u8>> {
|
||||||
let mut key = self.session_key.write().expect("couldn't lock session key");
|
let mut key = self.session_key.write().expect("couldn't lock session key");
|
||||||
key.take()
|
key.take()
|
||||||
}
|
}
|
||||||
|
@ -40,9 +40,9 @@
|
|||||||
//! * examples: `12`, `1`, `4`
|
//! * examples: `12`, `1`, `4`
|
||||||
//! * **log**: _[string]_ how much information to log; one of `"normal"`,
|
//! * **log**: _[string]_ how much information to log; one of `"normal"`,
|
||||||
//! `"debug"`, or `"critical"`
|
//! `"debug"`, or `"critical"`
|
||||||
//! * **session_key**: _[string]_ a 192-bit base64 encoded string (32
|
//! * **session_key**: _[string]_ a 256-bit base64 encoded string (44
|
||||||
//! characters) to use as the session key
|
//! characters) to use as the session key
|
||||||
//! * example: `"VheMwXIBygSmOlZAhuWl2B+zgvTN3WW5"`
|
//! * example: `"8Xui8SN4mI+7egV/9dlfYYLGQJeEx4+DwmSQLwDVXJg="`
|
||||||
//!
|
//!
|
||||||
//! ### Rocket.toml
|
//! ### Rocket.toml
|
||||||
//!
|
//!
|
||||||
@ -70,7 +70,7 @@
|
|||||||
//! workers = max(number_of_cpus, 2)
|
//! workers = max(number_of_cpus, 2)
|
||||||
//! log = "normal"
|
//! log = "normal"
|
||||||
//! # don't use this key! generate your own and keep it private!
|
//! # don't use this key! generate your own and keep it private!
|
||||||
//! session_key = "VheMwXIBygSmOlZAhuWl2B+zgvTN3WW5"
|
//! session_key = "8Xui8SN4mI+7egV/9dlfYYLGQJeEx4+DwmSQLwDVXJg="
|
||||||
//!
|
//!
|
||||||
//! [production]
|
//! [production]
|
||||||
//! address = "0.0.0.0"
|
//! address = "0.0.0.0"
|
||||||
@ -78,7 +78,7 @@
|
|||||||
//! workers = max(number_of_cpus, 2)
|
//! workers = max(number_of_cpus, 2)
|
||||||
//! log = "critical"
|
//! log = "critical"
|
||||||
//! # don't use this key! generate your own and keep it private!
|
//! # don't use this key! generate your own and keep it private!
|
||||||
//! session_key = "adL5fFIPmZBrlyHk2YT4NLV3YCk2gFXz"
|
//! session_key = "hPRYyVRiMyxpw5sBB1XeCMN1kFsDCqKvBi2QJxBVHQk="
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! The `workers` parameter is computed by Rocket automatically; the value above
|
//! The `workers` parameter is computed by Rocket automatically; the value above
|
||||||
@ -587,7 +587,7 @@ mod test {
|
|||||||
port = 7810
|
port = 7810
|
||||||
workers = 21
|
workers = 21
|
||||||
log = "critical"
|
log = "critical"
|
||||||
session_key = "01234567890123456789012345678901"
|
session_key = "8Xui8SN4mI+7egV/9dlfYYLGQJeEx4+DwmSQLwDVXJg="
|
||||||
template_dir = "mine"
|
template_dir = "mine"
|
||||||
json = true
|
json = true
|
||||||
pi = 3.14
|
pi = 3.14
|
||||||
@ -598,7 +598,7 @@ mod test {
|
|||||||
.port(7810)
|
.port(7810)
|
||||||
.workers(21)
|
.workers(21)
|
||||||
.log_level(LoggingLevel::Critical)
|
.log_level(LoggingLevel::Critical)
|
||||||
.session_key("01234567890123456789012345678901")
|
.session_key("8Xui8SN4mI+7egV/9dlfYYLGQJeEx4+DwmSQLwDVXJg=")
|
||||||
.extra("template_dir", "mine")
|
.extra("template_dir", "mine")
|
||||||
.extra("json", true)
|
.extra("json", true)
|
||||||
.extra("pi", 3.14);
|
.extra("pi", 3.14);
|
||||||
@ -873,19 +873,19 @@ mod test {
|
|||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(RocketConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
session_key = "VheMwXIBygSmOlZAhuWl2B+zgvTN3WW5"
|
session_key = "TpUiXK2d/v5DFxJnWL12suJKPExKR8h9zd/o+E7SU+0="
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
default_config(Staging).session_key(
|
default_config(Staging).session_key(
|
||||||
"VheMwXIBygSmOlZAhuWl2B+zgvTN3WW5"
|
"TpUiXK2d/v5DFxJnWL12suJKPExKR8h9zd/o+E7SU+0="
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(RocketConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
session_key = "adL5fFIPmZBrlyHk2YT4NLV3YCk2gFXz"
|
session_key = "jTyprDberFUiUFsJ3vcb1XKsYHWNBRvWAnXTlbTgGFU="
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
default_config(Staging).session_key(
|
default_config(Staging).session_key(
|
||||||
"adL5fFIPmZBrlyHk2YT4NLV3YCk2gFXz"
|
"jTyprDberFUiUFsJ3vcb1XKsYHWNBRvWAnXTlbTgGFU="
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,62 @@
|
|||||||
use http::Header;
|
use http::Header;
|
||||||
|
|
||||||
pub use cookie::Cookie;
|
use std::cell::RefMut;
|
||||||
pub use cookie::CookieJar;
|
|
||||||
pub use cookie::CookieBuilder;
|
|
||||||
|
|
||||||
/// Type alias to a `'static` CookieJar.
|
pub use cookie::{Cookie, CookieJar, Iter, CookieBuilder, Delta};
|
||||||
///
|
|
||||||
/// A `CookieJar` should never be used without a `'static` lifetime. As a
|
|
||||||
/// result, you should always use this alias.
|
|
||||||
pub type Cookies = self::CookieJar<'static>;
|
|
||||||
|
|
||||||
impl<'c> From<Cookie<'c>> for Header<'static> {
|
#[derive(Debug)]
|
||||||
fn from(cookie: Cookie) -> Header<'static> {
|
pub enum Cookies<'a> {
|
||||||
|
Jarred(RefMut<'a, CookieJar>),
|
||||||
|
Empty(CookieJar)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<RefMut<'a, CookieJar>> for Cookies<'a> {
|
||||||
|
fn from(jar: RefMut<'a, CookieJar>) -> Cookies<'a> {
|
||||||
|
Cookies::Jarred(jar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Cookies<'a> {
|
||||||
|
pub(crate) fn empty() -> Cookies<'static> {
|
||||||
|
Cookies::Empty(CookieJar::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, name: &str) -> Option<&Cookie<'static>> {
|
||||||
|
match *self {
|
||||||
|
Cookies::Jarred(ref jar) => jar.get(name),
|
||||||
|
Cookies::Empty(_) => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(&mut self, cookie: Cookie<'static>) {
|
||||||
|
if let Cookies::Jarred(ref mut jar) = *self {
|
||||||
|
jar.add(cookie)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove(&mut self, cookie: Cookie<'static>) {
|
||||||
|
if let Cookies::Jarred(ref mut jar) = *self {
|
||||||
|
jar.remove(cookie)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> Iter {
|
||||||
|
match *self {
|
||||||
|
Cookies::Jarred(ref jar) => jar.iter(),
|
||||||
|
Cookies::Empty(ref jar) => jar.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delta(&self) -> Delta {
|
||||||
|
match *self {
|
||||||
|
Cookies::Jarred(ref jar) => jar.delta(),
|
||||||
|
Cookies::Empty(ref jar) => jar.delta()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'c> From<&'a Cookie<'c>> for Header<'static> {
|
||||||
|
fn from(cookie: &Cookie) -> Header<'static> {
|
||||||
Header::new("Set-Cookie", cookie.encoded().to_string())
|
Header::new("Set-Cookie", cookie.encoded().to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -340,10 +340,10 @@ impl<'h> HeaderMap<'h> {
|
|||||||
///
|
///
|
||||||
/// let mut map = HeaderMap::new();
|
/// let mut map = HeaderMap::new();
|
||||||
///
|
///
|
||||||
/// map.add(Cookie::new("a", "b"));
|
/// map.add(&Cookie::new("a", "b"));
|
||||||
/// assert_eq!(map.get("Set-Cookie").count(), 1);
|
/// assert_eq!(map.get("Set-Cookie").count(), 1);
|
||||||
///
|
///
|
||||||
/// map.add(Cookie::new("c", "d"));
|
/// map.add(&Cookie::new("c", "d"));
|
||||||
/// assert_eq!(map.get("Set-Cookie").count(), 2);
|
/// assert_eq!(map.get("Set-Cookie").count(), 2);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -104,6 +104,7 @@ extern crate state;
|
|||||||
extern crate cookie;
|
extern crate cookie;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
extern crate memchr;
|
extern crate memchr;
|
||||||
|
extern crate base64;
|
||||||
|
|
||||||
#[cfg(test)] #[macro_use] extern crate lazy_static;
|
#[cfg(test)] #[macro_use] extern crate lazy_static;
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for Method {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'r> FromRequest<'a, 'r> for &'a Cookies {
|
impl<'a, 'r> FromRequest<'a, 'r> for Cookies<'a> {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
|
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
|
||||||
|
@ -14,6 +14,8 @@ use router::Route;
|
|||||||
use http::uri::{URI, Segments};
|
use http::uri::{URI, Segments};
|
||||||
use http::{Method, ContentType, Header, HeaderMap, Cookie, Cookies};
|
use http::{Method, ContentType, Header, HeaderMap, Cookie, Cookies};
|
||||||
|
|
||||||
|
use http::CookieJar;
|
||||||
|
|
||||||
use http::hyper;
|
use http::hyper;
|
||||||
|
|
||||||
/// The type of an incoming web request.
|
/// The type of an incoming web request.
|
||||||
@ -29,7 +31,7 @@ pub struct Request<'r> {
|
|||||||
headers: HeaderMap<'r>,
|
headers: HeaderMap<'r>,
|
||||||
remote: Option<SocketAddr>,
|
remote: Option<SocketAddr>,
|
||||||
params: RefCell<Vec<(usize, usize)>>,
|
params: RefCell<Vec<(usize, usize)>>,
|
||||||
cookies: Cookies,
|
cookies: RefCell<CookieJar>,
|
||||||
state: Option<&'r Container>,
|
state: Option<&'r Container>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +56,7 @@ impl<'r> Request<'r> {
|
|||||||
headers: HeaderMap::new(),
|
headers: HeaderMap::new(),
|
||||||
remote: None,
|
remote: None,
|
||||||
params: RefCell::new(Vec::new()),
|
params: RefCell::new(Vec::new()),
|
||||||
cookies: Cookies::new(&[]),
|
cookies: RefCell::new(CookieJar::new()),
|
||||||
state: None
|
state: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -251,15 +253,24 @@ impl<'r> Request<'r> {
|
|||||||
/// request.cookies().add(Cookie::new("key", "val"));
|
/// request.cookies().add(Cookie::new("key", "val"));
|
||||||
/// request.cookies().add(Cookie::new("ans", format!("life: {}", 38 + 4)));
|
/// request.cookies().add(Cookie::new("ans", format!("life: {}", 38 + 4)));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
pub fn cookies(&self) -> &Cookies {
|
pub fn cookies(&self) -> Cookies {
|
||||||
&self.cookies
|
match self.cookies.try_borrow_mut() {
|
||||||
|
Ok(jar) => Cookies::from(jar),
|
||||||
|
Err(_) => {
|
||||||
|
error_!("Multiple `Cookies` instances are active at once.");
|
||||||
|
info_!("An instance of `Cookies` must be dropped before another \
|
||||||
|
can be retrieved.");
|
||||||
|
warn_!("The retrieved `Cookies` instance will be empty.");
|
||||||
|
Cookies::empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replace all of the cookies in `self` with `cookies`.
|
/// Replace all of the cookies in `self` with `cookies`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn set_cookies(&mut self, cookies: Cookies) {
|
pub(crate) fn set_cookies(&mut self, jar: CookieJar) {
|
||||||
self.cookies = cookies;
|
self.cookies = RefCell::new(jar);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `Some` of the Content-Type header of `self`. If the header is
|
/// Returns `Some` of the Content-Type header of `self`. If the header is
|
||||||
@ -419,7 +430,7 @@ impl<'r> Request<'r> {
|
|||||||
|
|
||||||
// Set the request cookies, if they exist. TODO: Use session key.
|
// Set the request cookies, if they exist. TODO: Use session key.
|
||||||
if let Some(cookie_headers) = h_headers.get_raw("Cookie") {
|
if let Some(cookie_headers) = h_headers.get_raw("Cookie") {
|
||||||
let mut cookies = Cookies::new(&[]);
|
let mut jar = CookieJar::new();
|
||||||
for header in cookie_headers {
|
for header in cookie_headers {
|
||||||
let raw_str = match ::std::str::from_utf8(header) {
|
let raw_str = match ::std::str::from_utf8(header) {
|
||||||
Ok(string) => string,
|
Ok(string) => string,
|
||||||
@ -432,11 +443,11 @@ impl<'r> Request<'r> {
|
|||||||
Err(_) => continue
|
Err(_) => continue
|
||||||
};
|
};
|
||||||
|
|
||||||
cookies.add_original(cookie);
|
jar.add_original(cookie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
request.set_cookies(cookies);
|
request.set_cookies(jar);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the rest of the headers.
|
// Set the rest of the headers.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::convert::AsRef;
|
use std::convert::AsRef;
|
||||||
|
|
||||||
use time::{self, Duration};
|
use time::Duration;
|
||||||
|
|
||||||
use outcome::IntoOutcome;
|
use outcome::IntoOutcome;
|
||||||
use response::{Response, Responder};
|
use response::{Response, Responder};
|
||||||
@ -184,7 +184,7 @@ impl<'r, R: Responder<'r>> Responder<'r> for Flash<R> {
|
|||||||
trace_!("Flash: setting message: {}:{}", self.name, self.message);
|
trace_!("Flash: setting message: {}:{}", self.name, self.message);
|
||||||
let cookie = self.cookie();
|
let cookie = self.cookie();
|
||||||
Response::build_from(self.responder.respond()?)
|
Response::build_from(self.responder.respond()?)
|
||||||
.header_adjoin(cookie)
|
.header_adjoin(&cookie)
|
||||||
.ok()
|
.ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,18 +220,12 @@ impl<'a, 'r> FromRequest<'a, 'r> for Flash<()> {
|
|||||||
|
|
||||||
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
|
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
|
||||||
trace_!("Flash: attemping to retrieve message.");
|
trace_!("Flash: attemping to retrieve message.");
|
||||||
let r = request.cookies().find(FLASH_COOKIE_NAME).ok_or(()).and_then(|cookie| {
|
let r = request.cookies().get(FLASH_COOKIE_NAME).ok_or(()).and_then(|cookie| {
|
||||||
trace_!("Flash: retrieving message: {:?}", cookie);
|
trace_!("Flash: retrieving message: {:?}", cookie);
|
||||||
|
|
||||||
// Create the "deletion" cookie. We'll use it to clear the cookie.
|
// Delete the flash cookie from the jar.
|
||||||
let delete_cookie = Cookie::build(FLASH_COOKIE_NAME, "")
|
let orig_cookie = Cookie::build(FLASH_COOKIE_NAME, "").path("/").finish();
|
||||||
.max_age(Duration::seconds(0))
|
request.cookies().remove(orig_cookie);
|
||||||
.expires(time::now() - Duration::days(365))
|
|
||||||
.path("/")
|
|
||||||
.finish();
|
|
||||||
|
|
||||||
// Add the deletion to the cookie jar, replacing the existing cookie.
|
|
||||||
request.cookies().add(delete_cookie);
|
|
||||||
|
|
||||||
// Parse the flash message.
|
// Parse the flash message.
|
||||||
let content = cookie.value();
|
let content = cookie.value();
|
||||||
|
Loading…
Reference in New Issue
Block a user