use std::ops::{Deref, DerefMut};
use bytes::Bytes;
use cookie::Cookie;
use http::{HeaderMap, HeaderValue, header};
#[derive(Default)]
pub struct CookieStore {
inner: cookie_store::CookieStore,
}
impl CookieStore {
pub fn new(cookie_store: cookie_store::CookieStore) -> Self {
Self {
inner: cookie_store,
}
}
pub fn add_cookie_header(&self, headers: &mut HeaderMap, request_url: &url::Url) {
if let Some(header_value) = self.cookies(request_url) {
headers.insert(header::COOKIE, header_value);
}
}
pub fn store_response_headers(&mut self, headers: &HeaderMap, request_url: &url::Url) {
let mut set_cookie_headers = headers.get_all(header::SET_COOKIE).iter().peekable();
if set_cookie_headers.peek().is_some() {
let cookie_iter = set_cookie_headers.filter_map(|val| {
std::str::from_utf8(val.as_bytes())
.ok()
.and_then(|val| Cookie::parse(val).map(|c| c.into_owned()).ok())
});
self.inner.store_response_cookies(cookie_iter, request_url);
}
}
pub fn cookies(&self, request_url: &url::Url) -> Option<HeaderValue> {
let cookie_iter = self.inner.get_request_values(request_url);
let mut size = 0;
let cookies: Vec<(&str, &str)> = cookie_iter.collect::<Vec<_>>();
if cookies.is_empty() {
return None;
}
for (key, value) in &cookies {
size += key.len() + value.len();
}
if size == 0 {
return None;
}
size += 3 * cookies.len() - 2;
let mut s = String::with_capacity(size);
let mut cookie_iter = cookies.iter();
let first = cookie_iter.next().unwrap();
s.push_str(first.0);
s.push('=');
s.push_str(first.1);
for (key, value) in cookie_iter {
s.push_str("; ");
s.push_str(key);
s.push('=');
s.push_str(value);
}
HeaderValue::from_maybe_shared(Bytes::from(s)).ok()
}
}
impl Deref for CookieStore {
type Target = cookie_store::CookieStore;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for CookieStore {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}