Skip to content

Commit 96acc0c

Browse files
authored
Merge pull request #484 from jbr/bugfix-parse-cookie-header
🐞 correctly parse multiple values out of the Cookie header
2 parents b7252dd + f368310 commit 96acc0c

File tree

2 files changed

+27
-15
lines changed

2 files changed

+27
-15
lines changed

src/cookies/middleware.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::response::CookieEvent;
22
use crate::utils::BoxFuture;
33
use crate::{Middleware, Next, Request};
44

5-
use cookie::CookieJar;
5+
use cookie::{Cookie, CookieJar};
66
use http_types::headers;
77

88
use std::sync::{Arc, RwLock};
@@ -77,16 +77,21 @@ pub(crate) struct CookieData {
7777

7878
impl CookieData {
7979
pub(crate) fn from_request<S>(req: &Request<S>) -> Self {
80-
let cookie_jar = req.request.cookies().and_then(|cookies| {
81-
let mut jar = CookieJar::new();
82-
for cookie in cookies.into_iter() {
83-
jar.add_original(cookie.into_owned());
84-
}
80+
let mut jar = CookieJar::new();
8581

86-
Ok(jar)
87-
});
88-
let content = Arc::new(RwLock::new(cookie_jar.unwrap_or_default()));
82+
if let Some(cookie_headers) = req.header(&headers::COOKIE) {
83+
for cookie_header in cookie_headers {
84+
// spec says there should be only one, so this is permissive
85+
for pair in cookie_header.as_str().split(";") {
86+
if let Ok(cookie) = Cookie::parse_encoded(String::from(pair)) {
87+
jar.add_original(cookie);
88+
}
89+
}
90+
}
91+
}
8992

90-
CookieData { content }
93+
CookieData {
94+
content: Arc::new(RwLock::new(jar)),
95+
}
9196
}
9297
}

tests/cookies.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ use tide::{Request, Response, Server, StatusCode};
88
static COOKIE_NAME: &str = "testCookie";
99

1010
async fn retrieve_cookie(cx: Request<()>) -> tide::Result<String> {
11-
Ok(cx.cookie(COOKIE_NAME).unwrap().value().to_string())
11+
Ok(format!(
12+
"{} and also {}",
13+
cx.cookie(COOKIE_NAME).unwrap().value(),
14+
cx.cookie("secondTestCookie").unwrap().value()
15+
))
1216
}
1317

1418
async fn set_cookie(_req: Request<()>) -> tide::Result {
@@ -47,8 +51,11 @@ fn make_request(endpoint: &str) -> http_types::Response {
4751
http_types::Method::Get,
4852
format!("http://example.com{}", endpoint).parse().unwrap(),
4953
);
50-
req.insert_header(http_types::headers::COOKIE, "testCookie=RequestCookieValue")
51-
.unwrap();
54+
req.insert_header(
55+
http_types::headers::COOKIE,
56+
"testCookie=RequestCookieValue; secondTestCookie=Other%3BCookie%20Value",
57+
)
58+
.unwrap();
5259

5360
server.simulate(req).unwrap()
5461
}
@@ -61,10 +68,10 @@ fn successfully_retrieve_request_cookie() {
6168
let body = block_on(async move {
6269
let mut buffer = Vec::new();
6370
res.read_to_end(&mut buffer).await.unwrap();
64-
buffer
71+
String::from_utf8(buffer).unwrap()
6572
});
6673

67-
assert_eq!(&*body, &*b"RequestCookieValue");
74+
assert_eq!(&body, "RequestCookieValue and also Other;Cookie Value");
6875
}
6976

7077
#[test]

0 commit comments

Comments
 (0)