Improve redirect behaviour to clear headers and reevaluate sent cookies. Implement storage-related cookie behaviour such as domain and path matching that cookie-rs doesn't require. Remove stored cookies when an empty value is stored. Document cookie code.

This commit is contained in:
Josh Matthews 2014-12-30 17:09:34 -05:00
parent ae2b74c783
commit 24c8896f88
10 changed files with 270 additions and 265 deletions

View file

@ -1,3 +1,10 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Implementation of cookie storage as specified in
//! http://tools.ietf.org/html/rfc6265
use url::Url;
use cookie::Cookie;
@ -12,32 +19,64 @@ impl CookieStorage {
}
}
pub fn push(&mut self, cookie: Cookie) {
match self.cookies.iter().position(|c| c.domain == cookie.domain && c.path == cookie.path && c.name == cookie.name) {
Some(ind) => { self.cookies.remove(ind); }
None => {}
};
// http://tools.ietf.org/html/rfc6265#section-5.3
pub fn remove(&mut self, cookie: &Cookie) -> Option<Cookie> {
// Step 1
let position = self.cookies.iter().position(|c| {
c.cookie.domain == cookie.cookie.domain &&
c.cookie.path == cookie.cookie.path &&
c.cookie.name == cookie.cookie.name
});
self.cookies.push(cookie);
if let Some(ind) = position {
Some(self.cookies.remove(ind))
} else {
None
}
}
// http://tools.ietf.org/html/rfc6265#section-5.3
pub fn push(&mut self, mut cookie: Cookie, request: &Url) {
// Step 11
if let Some(old_cookie) = self.remove(&cookie) {
// Step 11.2
if old_cookie.cookie.httponly && !request.scheme.starts_with("http") {
self.cookies.push(old_cookie);
} else {
// Step 11.3
cookie.created_at = old_cookie.created_at;
// Step 12
self.cookies.push(cookie);
}
}
}
// http://tools.ietf.org/html/rfc6265#section-5.4
pub fn cookies_for_url(&mut self, url: Url) -> Option<String> {
let filterer = |&:c: &&mut Cookie| -> bool {
error!(" === SENT COOKIE : {} {} {} {}", c.name, c.value, c.domain, c.path);
error!(" === SENT COOKIE RESULT {}", c.appropriate_for_url(url.clone()));
info!(" === SENT COOKIE : {} {} {:?} {:?}", c.cookie.name, c.cookie.value, c.cookie.domain, c.cookie.path);
info!(" === SENT COOKIE RESULT {}", c.appropriate_for_url(url.clone()));
// Step 1
c.appropriate_for_url(url.clone())
};
let mut url_cookies = self.cookies.iter_mut().filter(filterer);
// TODO Step 2
let reducer = |&:acc: String, c: &mut Cookie| -> String {
// Step 3
c.touch();
// Step 4
(match acc.len() {
0 => acc,
_ => acc + ";"
}) + c.name.as_slice() + "=" + c.value.as_slice()
}) + c.cookie.name.as_slice() + "=" + c.cookie.value.as_slice()
};
let result = url_cookies.fold("".to_string(), reducer);
error!(" === COOKIES SENT: {}", result);
info!(" === COOKIES SENT: {}", result);
match result.len() {
0 => None,
_ => Some(result)