fix(net): default cookie Path to the request directory (RFC 6265 5.1.4) (#403)
* fix(net): default cookie Path to the request directory (RFC 6265 5.1.4) When a Set-Cookie carried no Path attribute, the jar stored the full request path as the cookie's path. RFC 6265 5.1.4 default-path is the request URI's directory — the path up to but not including the right-most '/'. Storing the full path scoped a session cookie to the exact URL that set it: a cookie set on GET /app/login was stored with path=/app/login and then, because path-match (5.1.4, fixed earlier) requires a '/' boundary, was not sent to /app/dashboard. The user appeared logged out on the very next navigation. Add default_cookie_path() implementing the RFC algorithm and use it as the initial path in both set_cookie (HTTP) and set_cookie_from_js (document.cookie). An explicit Path attribute still overrides it. Tests cover the algorithm and the end-to-end 'cookie set on /app/login is sent to /app/dashboard' path for both the HTTP and JS entry points; both failed before this change. * fix(cdp): apply RFC 6265 default cookie Path to CDP-injected cookies Network.setCookie/setCookies (the Puppeteer page.setCookie and Playwright addCookies surface) derived the cookie Path from the full request URL when the caller omitted path, the same bug the parent commit fixed for Set-Cookie responses. Reuse default_cookie_path (now pub) so a cookie set under /v1/things scopes to /v1 and is resent on sibling paths. Fixes the CDP half of #401. Correct the test that locked in the old full-path behavior and add a case confirming an explicit Path still wins. --------- Co-authored-by: SGavrl <[email protected]>
This commit is contained in:
1 parent
c8c78ba229
commit
5ada3b404b
3 files changed
+100
-4
No files matched your search
@@ -31,7 +31,11 @@ pub fn parse_cdp_cookie(value: &Value) -> Option<CookieInfo> {
|
||||
.get("path")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|s| s.to_string())
|
||||
.or_else(|| url_parsed.as_ref().map(|u| u.path().to_string()))
|
||||
.or_else(|| {
|
||||
url_parsed
|
||||
.as_ref()
|
||||
.map(|u| obscura_net::default_cookie_path(u.path()))
|
||||
})
|
||||
.unwrap_or_else(|| DEFAULT_COOKIE_PATH.to_string());
|
||||
|
||||
let secure = value.get("secure").and_then(|v| v.as_bool()).unwrap_or(false);
|
||||
@@ -118,6 +122,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn parse_with_url_fallback_for_domain_and_path() {
|
||||
// RFC 6265 5.1.4 default-path: a cookie set under /v1/things with no
|
||||
// explicit Path is scoped to the directory /v1, not the full request
|
||||
// path. Puppeteer's page.setCookie / Playwright's addCookies reach this
|
||||
// path when the caller omits `path`.
|
||||
let v = json!({
|
||||
"name": "tok",
|
||||
"value": "xyz",
|
||||
@@ -125,6 +133,19 @@ mod tests {
|
||||
});
|
||||
let c = parse_cdp_cookie(&v).unwrap();
|
||||
assert_eq!(c.domain, "api.example.com");
|
||||
assert_eq!(c.path, "/v1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_explicit_path_overrides_default() {
|
||||
// An explicit Path attribute wins over the RFC default-path.
|
||||
let v = json!({
|
||||
"name": "tok",
|
||||
"value": "xyz",
|
||||
"url": "https://api.example.com/v1/things",
|
||||
"path": "/v1/things",
|
||||
});
|
||||
let c = parse_cdp_cookie(&v).unwrap();
|
||||
assert_eq!(c.path, "/v1/things");
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user