From 9ff42dd3a4550678deda26adf767803547881806 Mon Sep 17 00:00:00 2001 From: Andrew Bastin Date: Mon, 23 Oct 2023 18:59:49 +0530 Subject: [PATCH] feat: implement initial cookie service --- packages/hoppscotch-common/package.json | 3 + .../src/services/cookie-jar.service.ts | 75 +++++++++++++++++++ pnpm-lock.yaml | 62 ++++++--------- 3 files changed, 101 insertions(+), 39 deletions(-) create mode 100644 packages/hoppscotch-common/src/services/cookie-jar.service.ts diff --git a/packages/hoppscotch-common/package.json b/packages/hoppscotch-common/package.json index 8cb17eb43..e26e5f749 100644 --- a/packages/hoppscotch-common/package.json +++ b/packages/hoppscotch-common/package.json @@ -52,6 +52,7 @@ "acorn-walk": "^8.2.0", "axios": "^1.4.0", "buffer": "^6.0.3", + "cookie-es": "^1.0.0", "dioc": "workspace:^", "esprima": "^4.0.1", "events": "^3.3.0", @@ -76,6 +77,8 @@ "process": "^0.11.10", "qs": "^6.11.2", "rxjs": "^7.8.1", + "set-cookie-parser": "^2.6.0", + "set-cookie-parser-es": "^1.0.5", "socket.io-client-v2": "npm:socket.io-client@^2.4.0", "socket.io-client-v3": "npm:socket.io-client@^3.1.3", "socket.io-client-v4": "npm:socket.io-client@^4.4.1", diff --git a/packages/hoppscotch-common/src/services/cookie-jar.service.ts b/packages/hoppscotch-common/src/services/cookie-jar.service.ts new file mode 100644 index 000000000..48e958ab1 --- /dev/null +++ b/packages/hoppscotch-common/src/services/cookie-jar.service.ts @@ -0,0 +1,75 @@ +import { Service } from "dioc" +import { ref } from "vue" +import { parseString as setCookieParse } from "set-cookie-parser-es" + +export type CookieDef = { + name: string + value: string + domain: string + path: string + expires: string +} + +export class CookieJarService extends Service { + public static readonly ID = "COOKIE_JAR_SERVICE" + + /** + * The cookie jar that stores all relevant cookie info. + * The keys correspond to the domain of the cookie. + * The cookie strings are stored as an array of strings corresponding to the domain + */ + public cookieJar = ref(new Map()) + + constructor() { + super() + + // TODO: Remove this, only for testing + this.cookieJar.value.set("hoppscotch.io", [ + "cookie1=value1;", + "cookie2=value2;", + "cookie6=value6; Expires=Mon, 23 Oct 2023 14:53:22 GMT", + ]) + + this.cookieJar.value.set("echo.hoppscotch.io", [ + "cookie3=value3;", + "cookie4=value4; Path=/test", + "cookie5=value5; Expires=Mon, 23 Oct 2023 12:23:22 GMT", + ]) + } + + public parseSetCookieString(setCookieString: string) { + return setCookieParse(setCookieString) + } + + public getCookiesForURL(url: URL) { + const relevantDomains = Array.from(this.cookieJar.value.keys()).filter( + (domain) => url.hostname.endsWith(domain) + ) + + return relevantDomains + .flatMap((domain) => { + // Assemble the list of cookie entries from all the relevant domains + + const cookieStrings = this.cookieJar.value.get(domain)! // We know not nullable from how we filter above + + return cookieStrings.map((cookieString) => + this.parseSetCookieString(cookieString) + ) + }) + .filter((cookie) => { + // Perform the required checks on the cookies + + const passesPathCheck = url.pathname.startsWith(cookie.path ?? "/") + + const passesExpiresCheck = !cookie.expires + ? true + : cookie.expires.getTime() >= new Date().getTime() + + const passesSecureCheck = !cookie.secure + ? true + : url.protocol === "https:" + + return passesPathCheck && passesExpiresCheck && passesSecureCheck + }) + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 52774b8f9..fd18b84a1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -460,6 +460,9 @@ importers: buffer: specifier: ^6.0.3 version: 6.0.3 + cookie-es: + specifier: ^1.0.0 + version: 1.0.0 dioc: specifier: workspace:^ version: link:../dioc @@ -532,6 +535,12 @@ importers: rxjs: specifier: ^7.8.1 version: 7.8.1 + set-cookie-parser: + specifier: ^2.6.0 + version: 2.6.0 + set-cookie-parser-es: + specifier: ^1.0.5 + version: 1.0.5 socket.io-client-v2: specifier: npm:socket.io-client@^2.4.0 version: /socket.io-client@2.4.0 @@ -800,7 +809,7 @@ importers: version: 5.2.2 vite: specifier: ^4.5.0 - version: 4.5.0(@types/node@17.0.27) + version: 4.5.0(@types/node@17.0.27)(sass@1.53.0)(terser@5.24.0) packages/hoppscotch-js-sandbox: dependencies: @@ -13329,6 +13338,10 @@ packages: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} dev: true + /cookie-es@1.0.0: + resolution: {integrity: sha512-mWYvfOLrfEc996hlKcdABeIiPHUPC6DM2QYZdGGOvhOTbA3tjm2eBwqlJpoFdjC89NI4Qt6h0Pu06Mp+1Pj5OQ==} + dev: false + /cookie-parser@1.4.6: resolution: {integrity: sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==} engines: {node: '>= 0.8.0'} @@ -22306,6 +22319,14 @@ packages: /set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + /set-cookie-parser-es@1.0.5: + resolution: {integrity: sha512-nU27kVj4O6+a1wOOWB6uezxB9SWLCjEmYJr6eRBmkAZfOx/TBg2p0jkCl1dMgeYtmFRAJSGe4u9VN7dwPu9PRQ==} + dev: false + + /set-cookie-parser@2.6.0: + resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} + dev: false + /set-function-length@1.1.1: resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} engines: {node: '>= 0.4'} @@ -25308,7 +25329,7 @@ packages: fsevents: 2.3.3 dev: true - /vite@4.5.0(@types/node@17.0.27): + /vite@4.5.0(@types/node@17.0.27)(sass@1.53.0)(terser@5.24.0): resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -25340,48 +25361,11 @@ packages: esbuild: 0.18.20 postcss: 8.4.31 rollup: 3.29.4 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /vite@4.5.0(@types/node@17.0.27)(sass@1.53.0)(terser@5.24.0): - resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==} - engines: {node: ^14.18.0 || >=16.0.0} - hasBin: true - peerDependencies: - '@types/node': '>= 14' - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - '@types/node': 17.0.27 - esbuild: 0.18.20 - postcss: 8.4.28 - rollup: 3.29.4 sass: 1.53.0 terser: 5.24.0 optionalDependencies: fsevents: 2.3.3 dev: true - optional: true /vitest@0.29.8: resolution: {integrity: sha512-JIAVi2GK5cvA6awGpH0HvH/gEG9PZ0a/WoxdiV3PmqK+3CjQMf8c+J/Vhv4mdZ2nRyXFw66sAg6qz7VNkaHfDQ==}