mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Differentiate between HTTP and non-HTTP APIs for cookie operations. Fix some incorrect cookie removal operation logic. Order the returned cookies according to the spec. Make cookie unit tests pass.
This commit is contained in:
parent
24c8896f88
commit
14df9f8a70
7 changed files with 142 additions and 137 deletions
|
@ -7,6 +7,16 @@
|
|||
|
||||
use url::Url;
|
||||
use cookie::Cookie;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
/// The creator of a given cookie
|
||||
#[derive(PartialEq, Copy)]
|
||||
pub enum CookieSource {
|
||||
/// An HTTP API
|
||||
HTTP,
|
||||
/// A non-HTTP API
|
||||
NonHTTP,
|
||||
}
|
||||
|
||||
pub struct CookieStorage {
|
||||
cookies: Vec<Cookie>
|
||||
|
@ -20,7 +30,7 @@ impl CookieStorage {
|
|||
}
|
||||
|
||||
// http://tools.ietf.org/html/rfc6265#section-5.3
|
||||
pub fn remove(&mut self, cookie: &Cookie) -> Option<Cookie> {
|
||||
pub fn remove(&mut self, cookie: &Cookie, source: CookieSource) -> Result<Option<Cookie>, ()> {
|
||||
// Step 1
|
||||
let position = self.cookies.iter().position(|c| {
|
||||
c.cookie.domain == cookie.cookie.domain &&
|
||||
|
@ -29,42 +39,68 @@ impl CookieStorage {
|
|||
});
|
||||
|
||||
if let Some(ind) = position {
|
||||
Some(self.cookies.remove(ind))
|
||||
let c = self.cookies.remove(ind);
|
||||
|
||||
// http://tools.ietf.org/html/rfc6265#section-5.3 step 11.2
|
||||
if !c.cookie.httponly || source == CookieSource::HTTP {
|
||||
Ok(Some(c))
|
||||
} else {
|
||||
// Undo the removal.
|
||||
self.cookies.push(c);
|
||||
Err(())
|
||||
}
|
||||
} else {
|
||||
None
|
||||
Ok(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);
|
||||
}
|
||||
pub fn push(&mut self, mut cookie: Cookie, source: CookieSource) {
|
||||
let old_cookie = self.remove(&cookie, source);
|
||||
if old_cookie.is_err() {
|
||||
// This new cookie is not allowed to overwrite an existing one.
|
||||
return;
|
||||
}
|
||||
|
||||
if cookie.cookie.value.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 11
|
||||
if let Some(old_cookie) = old_cookie.unwrap() {
|
||||
// Step 11.3
|
||||
cookie.creation_time = old_cookie.creation_time;
|
||||
}
|
||||
|
||||
// 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> {
|
||||
pub fn cookies_for_url(&mut self, url: &Url, source: CookieSource) -> Option<String> {
|
||||
let filterer = |&:c: &&mut Cookie| -> bool {
|
||||
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()));
|
||||
info!(" === SENT COOKIE RESULT {}", c.appropriate_for_url(url, source));
|
||||
// Step 1
|
||||
c.appropriate_for_url(url.clone())
|
||||
c.appropriate_for_url(url, source)
|
||||
};
|
||||
|
||||
let mut url_cookies = self.cookies.iter_mut().filter(filterer);
|
||||
// Step 2
|
||||
let mut url_cookies: Vec<&mut Cookie> = self.cookies.iter_mut().filter(filterer).collect();
|
||||
url_cookies.sort_by(|a, b| {
|
||||
let a_path_len = a.cookie.path.as_ref().map(|p| p.len()).unwrap_or(0);
|
||||
let b_path_len = b.cookie.path.as_ref().map(|p| p.len()).unwrap_or(0);
|
||||
match a_path_len.cmp(&b_path_len) {
|
||||
Ordering::Equal => {
|
||||
let a_creation_time = a.creation_time.to_timespec();
|
||||
let b_creation_time = b.creation_time.to_timespec();
|
||||
a_creation_time.cmp(&b_creation_time)
|
||||
}
|
||||
result => result
|
||||
}
|
||||
});
|
||||
|
||||
// TODO Step 2
|
||||
|
||||
let reducer = |&:acc: String, c: &mut Cookie| -> String {
|
||||
let reducer = |&:acc: String, c: &mut &mut Cookie| -> String {
|
||||
// Step 3
|
||||
c.touch();
|
||||
|
||||
|
@ -74,7 +110,7 @@ impl CookieStorage {
|
|||
_ => acc + ";"
|
||||
}) + c.cookie.name.as_slice() + "=" + c.cookie.value.as_slice()
|
||||
};
|
||||
let result = url_cookies.fold("".to_string(), reducer);
|
||||
let result = url_cookies.iter_mut().fold("".to_string(), reducer);
|
||||
|
||||
info!(" === COOKIES SENT: {}", result);
|
||||
match result.len() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue