Skip to content
This repository was archived by the owner on Mar 3, 2025. It is now read-only.

Commit 3955cf1

Browse files
committed
add cookie jar support
1 parent 72d004e commit 3955cf1

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

src/templates/core/axios/request.hbs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,111 @@ import { CancelablePromise } from './CancelablePromise';
1111
import type { OnCancel } from './CancelablePromise';
1212
import type { OpenAPIConfig } from './OpenAPI';
1313

14+
interface Cookie {
15+
name: string;
16+
value: string;
17+
expires?: Date;
18+
path?: string;
19+
sameSite?: "Lax" | "None" | "Strict";
20+
secure?: boolean;
21+
}
22+
23+
class CookieJar {
24+
constructor(private jar = new Map<string, Cookie[]>()) {}
25+
26+
setCookie(url: URL, cookieStr: string) {
27+
const key = url.origin.toLowerCase();
28+
if (!this.jar.has(key)) {
29+
this.jar.set(key, []);
30+
}
31+
32+
const cookie = CookieJar.parse(cookieStr);
33+
this.jar.set(key, [...(this.jar.get(key)?.filter((c) => c.name !== cookie.name) || []), cookie]);
34+
}
35+
36+
getCookies(url: URL): Cookie[] {
37+
const key = url.origin.toLowerCase();
38+
if (!this.jar.get(key)) {
39+
return [];
40+
}
41+
42+
// Filter out expired cookies
43+
return this.jar.get(key)?.filter((cookie) => !cookie.expires || cookie.expires > new Date()) || [];
44+
}
45+
46+
static parse(str: string): Cookie {
47+
if (typeof str !== "string") {
48+
throw new Error("argument str must be a string");
49+
}
50+
51+
const parts = str.split(";").map((part) => part.trim());
52+
53+
let cookie: Cookie;
54+
55+
if (parts.length > 0) {
56+
const [name, value] = parts[0].split("=");
57+
if (!name || !value) {
58+
throw new Error("Invalid cookie");
59+
}
60+
61+
cookie = {
62+
name,
63+
value,
64+
};
65+
} else {
66+
throw new Error("Invalid cookie");
67+
}
68+
69+
parts.slice(1).forEach((part) => {
70+
const [name, value] = part.split("=");
71+
if (!name.trim()) {
72+
throw new Error("Invalid cookie");
73+
}
74+
75+
const nameLow = name.toLowerCase();
76+
// eslint-disable-next-line quotes
77+
const val = value?.charAt(0) === "'" || value?.charAt(0) === '"' ? value?.slice(1, -1) : value;
78+
if (nameLow === "expires") {
79+
cookie.expires = new Date(val);
80+
}
81+
if (nameLow === "path") {
82+
cookie.path = val;
83+
}
84+
if (nameLow === "samesite") {
85+
if (val !== "Lax" && val !== "None" && val !== "Strict") {
86+
throw new Error("Invalid cookie SameSite value");
87+
}
88+
cookie.sameSite = val;
89+
}
90+
if (nameLow === "secure") {
91+
cookie.secure = true;
92+
}
93+
});
94+
95+
return cookie;
96+
}
97+
}
98+
99+
const jar = new CookieJar();
100+
101+
axios.interceptors.response.use((response) => {
102+
if (Array.isArray(response.headers["set-cookie"])) {
103+
response.headers["set-cookie"].forEach((c) => {
104+
jar.setCookie(new URL(response.config.url), c);
105+
});
106+
}
107+
return response;
108+
});
109+
110+
axios.interceptors.request.use(function (config) {
111+
const cookies = jar.getCookies(new URL(config.url));
112+
113+
if (cookies?.length > 0) {
114+
config.headers.cookie = cookies.map((cookie) => `${cookie.name}=${cookie.value}`).join("; ");
115+
}
116+
return config;
117+
});
118+
14119
{{>functions/isDefined}}
15120

16121

0 commit comments

Comments
 (0)