From 4a70e5ac72b7bfee1cf760d078d4641287dbd045 Mon Sep 17 00:00:00 2001 From: Colin Casey Date: Wed, 25 Sep 2024 00:06:41 -0300 Subject: [PATCH] Restore missing `expiryDate` method Fixes #458 --- api/docs/tough-cookie.cookie.expirydate.md | 57 ++++++++++++++++++++++ api/docs/tough-cookie.cookie.md | 18 +++++++ api/tough-cookie.api.md | 1 + lib/__tests__/cookieJar.spec.ts | 4 ++ lib/cookie/cookie.ts | 29 +++++++++++ 5 files changed, 109 insertions(+) create mode 100644 api/docs/tough-cookie.cookie.expirydate.md diff --git a/api/docs/tough-cookie.cookie.expirydate.md b/api/docs/tough-cookie.cookie.expirydate.md new file mode 100644 index 00000000..2d32dfbf --- /dev/null +++ b/api/docs/tough-cookie.cookie.expirydate.md @@ -0,0 +1,57 @@ + + +[Home](./index.md) > [tough-cookie](./tough-cookie.md) > [Cookie](./tough-cookie.cookie.md) > [expiryDate](./tough-cookie.cookie.expirydate.md) + +## Cookie.expiryDate() method + +Similar to [Cookie.expiryTime()](./tough-cookie.cookie.expirytime.md), computes the absolute unix-epoch milliseconds that this cookie expires and returns it as a Date. + +The "Max-Age" attribute takes precedence over "Expires" (as per the RFC). The [Cookie.lastAccessed](./tough-cookie.cookie.lastaccessed.md) attribute (or the `now` parameter if given) is used to offset the [Cookie.maxAge](./tough-cookie.cookie.maxage.md) attribute. + +If Expires ([Cookie.expires](./tough-cookie.cookie.expires.md)) is set, that's returned. + +**Signature:** + +```typescript +expiryDate(now?: Date): Date | undefined; +``` + +## Parameters + + + +
+ +Parameter + + + + +Type + + + + +Description + + +
+ +now + + + + +Date + + + + +_(Optional)_ can be used to provide a time offset (instead of [Cookie.lastAccessed](./tough-cookie.cookie.lastaccessed.md)) to use when calculating the "Max-Age" value + + +
+**Returns:** + +Date \| undefined + diff --git a/api/docs/tough-cookie.cookie.md b/api/docs/tough-cookie.cookie.md index fe5547fd..99f736f6 100644 --- a/api/docs/tough-cookie.cookie.md +++ b/api/docs/tough-cookie.cookie.md @@ -452,6 +452,24 @@ Does a deep clone of this cookie, implemented exactly as `Cookie.fromJSON(cookie Encodes to a `Cookie` header value (specifically, the [Cookie.key](./tough-cookie.cookie.key.md) and [Cookie.value](./tough-cookie.cookie.value.md) properties joined with "="). + + + +[expiryDate(now)](./tough-cookie.cookie.expirydate.md) + + + + + + + +Similar to [Cookie.expiryTime()](./tough-cookie.cookie.expirytime.md), computes the absolute unix-epoch milliseconds that this cookie expires and returns it as a Date. + +The "Max-Age" attribute takes precedence over "Expires" (as per the RFC). The [Cookie.lastAccessed](./tough-cookie.cookie.lastaccessed.md) attribute (or the `now` parameter if given) is used to offset the [Cookie.maxAge](./tough-cookie.cookie.maxage.md) attribute. + +If Expires ([Cookie.expires](./tough-cookie.cookie.expires.md)) is set, that's returned. + + diff --git a/api/tough-cookie.api.md b/api/tough-cookie.api.md index a0409531..90e9e842 100644 --- a/api/tough-cookie.api.md +++ b/api/tough-cookie.api.md @@ -26,6 +26,7 @@ export class Cookie { creationIndex: number; domain: string | null; expires: Date | 'Infinity' | null; + expiryDate(now?: Date): Date | undefined; expiryTime(now?: Date): number | undefined; extensions: string[] | null; static fromJSON(str: unknown): Cookie | undefined; diff --git a/lib/__tests__/cookieJar.spec.ts b/lib/__tests__/cookieJar.spec.ts index 0f6c961d..0490a6f4 100644 --- a/lib/__tests__/cookieJar.spec.ts +++ b/lib/__tests__/cookieJar.spec.ts @@ -1227,6 +1227,7 @@ it('should fix issue #154 - Expiry should not be affected by creation date', asy ]) // the expiry time should be 60s from now (0) expect(initialCookies[0]?.expiryTime()).toBe(now + 60 * 1000) + expect(initialCookies[0]?.expiryDate()).toEqual(new Date(now + 60 * 1000)) // advance the time by 1s, so now = 1000 jest.advanceTimersByTime(1000) @@ -1247,6 +1248,9 @@ it('should fix issue #154 - Expiry should not be affected by creation date', asy ]) // the expiry time should be 60s from now (1000) expect(updatedCookies[0]?.expiryTime()).toBe(now + 60 * 1000 + 1000) + expect(updatedCookies[0]?.expiryDate()).toEqual( + new Date(now + 60 * 1000 + 1000), + ) }) it('should fix issue #261 - URL objects should be accepted in setCookie', async () => { diff --git a/lib/cookie/cookie.ts b/lib/cookie/cookie.ts index 031fcf71..6724febf 100644 --- a/lib/cookie/cookie.ts +++ b/lib/cookie/cookie.ts @@ -856,6 +856,35 @@ export class Cookie { return this.expires ? this.expires.getTime() : undefined } + /** + * Similar to {@link Cookie.expiryTime}, computes the absolute unix-epoch milliseconds that this cookie expires and returns it as a Date. + * + * The "Max-Age" attribute takes precedence over "Expires" (as per the RFC). The {@link Cookie.lastAccessed} attribute + * (or the `now` parameter if given) is used to offset the {@link Cookie.maxAge} attribute. + * + * If Expires ({@link Cookie.expires}) is set, that's returned. + * + * @param now - can be used to provide a time offset (instead of {@link Cookie.lastAccessed}) to use when calculating the "Max-Age" value + */ + expiryDate(now?: Date): Date | undefined { + const millisec = this.expiryTime(now) + if (millisec == Infinity) { + // The 31-bit value of 2147483647000 was chosen to be the MAX_TIME representable + // in tough-cookie though MDN states that the actual maximum value for a Date is 8.64e15. + // I'm guessing this is due to the Y2038 problem that would affect systems that store + // unix time as 32-bit integers. + // See: + // - https://github.com/salesforce/tough-cookie/commit/0616f70bf725e00c63d442544ad230c4f8b23357 + // - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#the_epoch_timestamps_and_invalid_date + // - https://en.wikipedia.org/wiki/Year_2038_problem + return new Date(2147483647000) + } else if (millisec == -Infinity) { + return new Date(0) + } else { + return millisec == undefined ? undefined : new Date(millisec) + } + } + /** * Indicates if the cookie has been persisted to a store or not. * @public