Skip to content

Commit 20cfe45

Browse files
added cookie jar and full cookie parsing
1 parent e13e2a2 commit 20cfe45

8 files changed

Lines changed: 1474 additions & 1 deletion

File tree

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ categories = ["network-programming", "no-std", "web-programming::http-client"]
1414
[lib]
1515
doctest = true
1616

17+
[features]
18+
default = []
19+
cookie-jar = []
20+
1721
[dependencies]
1822

1923
[target.'cfg(unix)'.dependencies]

src/client/http_client.rs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ use crate::transport::ConnectionPool;
1212
use alloc::string::String;
1313
use alloc::vec::Vec;
1414

15+
#[cfg(feature = "cookie-jar")]
16+
use crate::cookie_jar::CookieStore;
17+
1518
/// Generic HTTP client with customizable socket and DNS adapters
1619
///
1720
/// This client supports `no_std` environments and allows complete control over
@@ -34,6 +37,8 @@ pub struct HttpClient<S, D> {
3437
pool: ConnectionPool<S>,
3538
dns: D,
3639
config: Config,
40+
#[cfg(feature = "cookie-jar")]
41+
cookie_store: CookieStore,
3742
}
3843

3944
impl
@@ -54,6 +59,8 @@ impl
5459
pool: ConnectionPool::new(config.max_idle_per_host, config.idle_timeout),
5560
dns: crate::dns::resolver::OsDnsResolver::new(),
5661
config,
62+
#[cfg(feature = "cookie-jar")]
63+
cookie_store: CookieStore::new(),
5764
})
5865
}
5966

@@ -68,6 +75,8 @@ impl
6875
pool: ConnectionPool::new(config.max_idle_per_host, config.idle_timeout),
6976
dns: crate::dns::resolver::OsDnsResolver::new(),
7077
config,
78+
#[cfg(feature = "cookie-jar")]
79+
cookie_store: CookieStore::new(),
7180
})
7281
}
7382
}
@@ -90,6 +99,8 @@ where
9099
pool: ConnectionPool::new(config.max_idle_per_host, config.idle_timeout),
91100
dns,
92101
config,
102+
#[cfg(feature = "cookie-jar")]
103+
cookie_store: CookieStore::new(),
93104
}
94105
}
95106

@@ -104,6 +115,8 @@ where
104115
pool: ConnectionPool::new(config.max_idle_per_host, config.idle_timeout),
105116
dns,
106117
config,
118+
#[cfg(feature = "cookie-jar")]
119+
cookie_store: CookieStore::new(),
107120
}
108121
}
109122

@@ -239,6 +252,22 @@ where
239252
)
240253
}
241254

255+
/// Get mutable reference to the cookie store (requires cookie-jar feature)
256+
///
257+
/// Allows direct access to the cookie store for custom cookie management.
258+
#[cfg(feature = "cookie-jar")]
259+
pub const fn cookie_store_mut(&mut self) -> &mut CookieStore {
260+
&mut self.cookie_store
261+
}
262+
263+
/// Get reference to the cookie store (requires cookie-jar feature)
264+
///
265+
/// Allows read-only access to the cookie store.
266+
#[cfg(feature = "cookie-jar")]
267+
pub const fn cookie_store(&self) -> &CookieStore {
268+
&self.cookie_store
269+
}
270+
242271
/// Execute a `Request` object
243272
///
244273
/// # Errors
@@ -275,10 +304,46 @@ where
275304
let uri = Uri::parse(&current_url).map_err(Error::Parse)?;
276305
policy.validate_protocol(&uri)?;
277306

307+
// Add cookies to request headers if cookie-jar feature is enabled
308+
#[cfg(feature = "cookie-jar")]
309+
let mut headers_with_cookies = custom_headers.clone();
310+
#[cfg(feature = "cookie-jar")]
311+
{
312+
let is_secure = current_url.starts_with("https://");
313+
let cookie_header = self
314+
.cookie_store
315+
.get_request_cookies(&current_url, is_secure);
316+
if !cookie_header.is_empty() {
317+
headers_with_cookies.insert("Cookie", &cookie_header);
318+
}
319+
}
320+
321+
#[cfg(feature = "cookie-jar")]
322+
let headers_to_use = &headers_with_cookies;
323+
#[cfg(not(feature = "cookie-jar"))]
324+
let headers_to_use = custom_headers;
325+
278326
// Execute single HTTP request
279327
let mut executor = RequestExecutor::new(&mut self.pool, &self.dns, &self.config);
280328
let body_slice = current_body.as_deref();
281-
let raw = executor.execute(&uri, current_method, custom_headers, body_slice)?;
329+
let raw = executor.execute(&uri, current_method, headers_to_use, body_slice)?;
330+
331+
// Store cookies from response if cookie-jar feature is enabled
332+
#[cfg(feature = "cookie-jar")]
333+
{
334+
let set_cookie_headers: Vec<String> = raw
335+
.headers
336+
.get_all("Set-Cookie")
337+
.into_iter()
338+
.map(alloc::string::ToString::to_string)
339+
.collect();
340+
341+
if !set_cookie_headers.is_empty() {
342+
self
343+
.cookie_store
344+
.store_response_cookies(&current_url, &set_cookie_headers);
345+
}
346+
}
282347

283348
// Process response and make policy decision
284349
match policy.process_raw_response(

0 commit comments

Comments
 (0)