Skip to content

Commit

Permalink
feat(http): add cookie for client
Browse files Browse the repository at this point in the history
  • Loading branch information
StellarisW committed Nov 1, 2024
1 parent 0b3d1e8 commit e49ab79
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 15 deletions.
16 changes: 9 additions & 7 deletions volo-http/src/client/cookie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! See [`CookieLayer`] for more details.

use motore::{layer::Layer, Service};
use parking_lot::RwLock;
use tokio::sync::Mutex;

use crate::{
context::ClientContext,
Expand All @@ -20,11 +20,11 @@ use crate::{
/// See [`CookieLayer`] for more details.
pub struct CookieService<S> {
inner: S,
cookie_store: RwLock<CookieStore>,
cookie_store: Mutex<CookieStore>,
}

impl<S> CookieService<S> {
fn new(inner: S, cookie_store: RwLock<CookieStore>) -> Self {
fn new(inner: S, cookie_store: Mutex<CookieStore>) -> Self {
Self {
inner,
cookie_store,
Expand Down Expand Up @@ -54,7 +54,8 @@ where
let (mut parts, body) = req.into_parts();
if parts.headers.get(http::header::COOKIE).is_none() {
self.cookie_store
.read()
.lock()
.await
.add_cookie_header(&mut parts.headers, url);
}
req = ClientRequest::from_parts(parts, body);
Expand All @@ -64,7 +65,8 @@ where

if let Some(url) = &url {
self.cookie_store
.write()
.lock()
.await
.store_response_headers(resp.headers(), url);
}

Expand All @@ -76,7 +78,7 @@ where
///
/// See [`CookieLayer::new`] for more details.
pub struct CookieLayer {
cookie_store: RwLock<CookieStore>,
cookie_store: Mutex<CookieStore>,
}

impl CookieLayer {
Expand All @@ -103,7 +105,7 @@ impl CookieLayer {
/// ```
pub fn new(cookie_store: cookie_store::CookieStore) -> Self {
Self {
cookie_store: RwLock::new(CookieStore::new(cookie_store)),
cookie_store: Mutex::new(CookieStore::new(cookie_store)),
}
}
}
Expand Down
39 changes: 35 additions & 4 deletions volo-http/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{cell::RefCell, error::Error, sync::Arc, time::Duration};
use faststr::FastStr;
use http::{
header::{self, HeaderMap, HeaderName, HeaderValue},
uri::Uri,
uri::{Scheme, Uri},
Method,
};
use metainfo::{MetaInfo, METAINFO};
Expand Down Expand Up @@ -882,6 +882,15 @@ impl<S> Client<S> {
request.headers_mut().insert(header::HOST, host);
}

#[cfg(feature = "cookie")]
{
let scheme = match target.is_https() {
true => Scheme::HTTPS,
false => Scheme::HTTP,
};
request.extensions_mut().insert(scheme);
}

let mut cx = ClientContext::new();
cx.rpc_info_mut().caller_mut().set_service_name(caller_name);
cx.rpc_info_mut().callee_mut().set_service_name(callee_name);
Expand Down Expand Up @@ -1307,14 +1316,36 @@ mod client_tests {
assert_eq!(cookies[0].name(), "key");
assert_eq!(cookies[0].value(), "value");

#[derive(serde::Deserialize)]
struct CookieResponse {
#[serde(default)]
cookies: HashMap<String, String>,
}
let resp = client
.get("http://httpbin.org/cookies")
.send()
.await
.unwrap();
let json = resp.into_json::<CookieResponse>().await.unwrap();
assert_eq!(json.cookies["key"], "value");

// test server delete cookie
_ = client
.get("http://httpbin.org/cookies/delete?key")
.send()
.await
.unwrap();
let resp = client.get(HTTPBIN_GET).send().await.unwrap();
let cookies = resp.cookies().collect::<Vec<_>>();
assert_eq!(cookies.len(), 0)
_ = client
.get("http://httpbin.org/delete?key")
.send()
.await
.unwrap();
let resp = client
.get("http://httpbin.org/cookies")
.send()
.await
.unwrap();
let json = resp.into_json::<CookieResponse>().await.unwrap();
assert_eq!(json.cookies.len(), 0);
}
}
10 changes: 9 additions & 1 deletion volo-http/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use http::{
header::{self, HeaderMap, HeaderName},
request::{Parts, Request},
uri::Scheme,
Uri,
};

Expand Down Expand Up @@ -38,6 +39,7 @@ mod sealed {
pub trait SealedRequestPartsExt {
fn headers(&self) -> &http::header::HeaderMap;
fn uri(&self) -> &http::Uri;
fn extensions(&self) -> &http::Extensions;
}
}

Expand All @@ -48,6 +50,9 @@ impl sealed::SealedRequestPartsExt for Parts {
fn uri(&self) -> &Uri {
&self.uri
}
fn extensions(&self) -> &http::Extensions {
&self.extensions
}
}
impl<B> sealed::SealedRequestPartsExt for Request<B> {
fn headers(&self) -> &HeaderMap {
Expand All @@ -56,6 +61,9 @@ impl<B> sealed::SealedRequestPartsExt for Request<B> {
fn uri(&self) -> &Uri {
self.uri()
}
fn extensions(&self) -> &http::Extensions {
self.extensions()
}
}

impl<T> RequestPartsExt for T
Expand All @@ -72,7 +80,7 @@ where

let mut url_str = String::new();

if let Some(scheme) = uri.scheme() {
if let Some(scheme) = self.extensions().get::<Scheme>() {
url_str.push_str(scheme.as_str());
url_str.push_str("://");
} else {
Expand Down
8 changes: 5 additions & 3 deletions volo-http/src/utils/cookie/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@ impl CookieStore {

/// Get [`HeaderValue`] from the cookie store
pub fn cookies(&self, request_url: &url::Url) -> Option<HeaderValue> {
let mut cookie_iter = self.inner.get_request_values(request_url);
let cookie_iter = self.inner.get_request_values(request_url);

let mut size = 0;

for (key, value) in cookie_iter.by_ref() {
let cookies: Vec<(&str, &str)> = cookie_iter.collect::<Vec<_>>();

for (key, value) in &cookies {
size += key.len() + value.len() + 3;
}

Expand All @@ -51,7 +53,7 @@ impl CookieStore {

let mut s = String::with_capacity(size);

for (name, value) in cookie_iter {
for (name, value) in cookies {
s.push_str(name);
s.push('=');
s.push_str(value);
Expand Down

0 comments on commit e49ab79

Please sign in to comment.