diff --git a/api/docs/tough-cookie.cookiejar.getcookies.md b/api/docs/tough-cookie.cookiejar.getcookies.md index 512f80a4..b3530cfe 100644 --- a/api/docs/tough-cookie.cookiejar.getcookies.md +++ b/api/docs/tough-cookie.cookiejar.getcookies.md @@ -9,7 +9,7 @@ Retrieve the list of cookies that can be sent in a Cookie header for the current **Signature:** ```typescript -getCookies(url: string, callback: Callback): void; +getCookies(url: string): Promise; ``` ## Parameters @@ -45,27 +45,11 @@ string The domain to store the cookie with. - - - -callback - - - - -[Callback](./tough-cookie.callback.md)<[Cookie](./tough-cookie.cookie.md)\[\]> - - - - -A function to call after a cookie has been successfully retrieved. - - **Returns:** -void +Promise<[Cookie](./tough-cookie.cookie.md)\[\]> ## Remarks diff --git a/api/docs/tough-cookie.cookiejar.getcookies_1.md b/api/docs/tough-cookie.cookiejar.getcookies_1.md index f842189f..5e6fbf8b 100644 --- a/api/docs/tough-cookie.cookiejar.getcookies_1.md +++ b/api/docs/tough-cookie.cookiejar.getcookies_1.md @@ -9,7 +9,7 @@ Retrieve the list of cookies that can be sent in a Cookie header for the current **Signature:** ```typescript -getCookies(url: string | URL, options: GetCookiesOptions | undefined, callback: Callback): void; +getCookies(url: string, callback: Callback): void; ``` ## Parameters @@ -37,7 +37,7 @@ url -string \| URL +string @@ -45,22 +45,6 @@ string \| URL The domain to store the cookie with. - - - -options - - - - -[GetCookiesOptions](./tough-cookie.getcookiesoptions.md) \| undefined - - - - -Configuration settings to use when retrieving the cookies. - - diff --git a/api/docs/tough-cookie.cookiejar.getcookies_2.md b/api/docs/tough-cookie.cookiejar.getcookies_2.md index 760ce4d2..5e7d236f 100644 --- a/api/docs/tough-cookie.cookiejar.getcookies_2.md +++ b/api/docs/tough-cookie.cookiejar.getcookies_2.md @@ -9,7 +9,7 @@ Retrieve the list of cookies that can be sent in a Cookie header for the current **Signature:** ```typescript -getCookies(url: string | URL, options?: GetCookiesOptions | undefined): Promise; +getCookies(url: string | URL, options: GetCookiesOptions | undefined, callback: Callback): void; ``` ## Parameters @@ -58,14 +58,30 @@ options -_(Optional)_ Configuration settings to use when retrieving the cookies. +Configuration settings to use when retrieving the cookies. + + + + + +callback + + + + +[Callback](./tough-cookie.callback.md)<[Cookie](./tough-cookie.cookie.md)\[\]> + + + + +A function to call after a cookie has been successfully retrieved. **Returns:** -Promise<[Cookie](./tough-cookie.cookie.md)\[\]> +void ## Remarks diff --git a/api/docs/tough-cookie.cookiejar.getcookies_3.md b/api/docs/tough-cookie.cookiejar.getcookies_3.md new file mode 100644 index 00000000..1aa8007a --- /dev/null +++ b/api/docs/tough-cookie.cookiejar.getcookies_3.md @@ -0,0 +1,75 @@ + + +[Home](./index.md) > [tough-cookie](./tough-cookie.md) > [CookieJar](./tough-cookie.cookiejar.md) > [getCookies](./tough-cookie.cookiejar.getcookies_3.md) + +## CookieJar.getCookies() method + +Retrieve the list of cookies that can be sent in a Cookie header for the current URL. + +**Signature:** + +```typescript +getCookies(url: string | URL, options?: GetCookiesOptions | undefined): Promise; +``` + +## Parameters + + + + +
+ +Parameter + + + + +Type + + + + +Description + + +
+ +url + + + + +string \| URL + + + + +The domain to store the cookie with. + + +
+ +options + + + + +[GetCookiesOptions](./tough-cookie.getcookiesoptions.md) \| undefined + + + + +_(Optional)_ Configuration settings to use when retrieving the cookies. + + +
+**Returns:** + +Promise<[Cookie](./tough-cookie.cookie.md)\[\]> + +## Remarks + +- The array of cookies returned will be sorted according to [cookieCompare()](./tough-cookie.cookiecompare.md). + +- The [Cookie.lastAccessed](./tough-cookie.cookie.lastaccessed.md) property will be updated on all returned cookies. + diff --git a/api/docs/tough-cookie.cookiejar.md b/api/docs/tough-cookie.cookiejar.md index 57a132d0..a1553724 100644 --- a/api/docs/tough-cookie.cookiejar.md +++ b/api/docs/tough-cookie.cookiejar.md @@ -275,7 +275,7 @@ Alias of [CookieJar.deserializeSync()](./tough-cookie.cookiejar.deserializesync. -[getCookies(url, callback)](./tough-cookie.cookiejar.getcookies.md) +[getCookies(url)](./tough-cookie.cookiejar.getcookies.md) @@ -289,7 +289,7 @@ Retrieve the list of cookies that can be sent in a Cookie header for the current -[getCookies(url, options, callback)](./tough-cookie.cookiejar.getcookies_1.md) +[getCookies(url, callback)](./tough-cookie.cookiejar.getcookies_1.md) @@ -303,7 +303,21 @@ Retrieve the list of cookies that can be sent in a Cookie header for the current -[getCookies(url, options)](./tough-cookie.cookiejar.getcookies_2.md) +[getCookies(url, options, callback)](./tough-cookie.cookiejar.getcookies_2.md) + + + + + + + +Retrieve the list of cookies that can be sent in a Cookie header for the current URL. + + + + + +[getCookies(url, options)](./tough-cookie.cookiejar.getcookies_3.md) diff --git a/api/tough-cookie.api.md b/api/tough-cookie.api.md index 8553381d..672106f6 100644 --- a/api/tough-cookie.api.md +++ b/api/tough-cookie.api.md @@ -81,6 +81,7 @@ export class CookieJar { static deserialize(strOrObj: string | object, store?: Store | Callback, callback?: Callback): unknown; static deserializeSync(strOrObj: string | SerializedCookieJar, store?: Store): CookieJar; static fromJSON(jsonString: string | SerializedCookieJar, store?: Store): CookieJar; + getCookies(url: string): Promise; getCookies(url: string, callback: Callback): void; getCookies(url: string | URL, options: GetCookiesOptions | undefined, callback: Callback): void; getCookies(url: string | URL, options?: GetCookiesOptions | undefined): Promise; diff --git a/lib/__tests__/cookieJar.spec.ts b/lib/__tests__/cookieJar.spec.ts index cc1d52e4..ebc8233f 100644 --- a/lib/__tests__/cookieJar.spec.ts +++ b/lib/__tests__/cookieJar.spec.ts @@ -1169,12 +1169,12 @@ it('should fix issue #144', async () => { ]) }) -it('should fix issue #145 - missing 2nd url parameter', () => { +it('should fix issue #145 - missing 2nd url parameter', async () => { const cookieJar = new CookieJar() - expect( + await expect( // @ts-expect-error test case explicitly violates the expected function signature - () => cookieJar.setCookie('x=y; Domain=example.com; Path=/'), - ).toThrowError('`url` argument is not a string or URL.') + cookieJar.setCookie('x=y; Domain=example.com; Path=/', undefined), + ).rejects.toThrow('`url` argument is not a string or URL.') }) it('should fix issue #197 - CookieJar().setCookie throws an error when empty cookie is passed', async () => { @@ -1488,6 +1488,30 @@ describe('Synchronous API on async CookieJar', () => { }) }) +describe('validation errors invoke callbacks', () => { + it('getCookies', () => { + const invalidUrl = {} + const cookieJar = new CookieJar() + // @ts-expect-error deliberately trigger validation error + void cookieJar.getCookies(invalidUrl, (err) => { + expect(err).toMatchObject({ + message: '`url` argument is not a string or URL.', + }) + }) + }) + + it('setCookie', () => { + const invalidUrl = {} + const cookieJar = new CookieJar() + // @ts-expect-error deliberately trigger validation error + void cookieJar.setCookie('a=b', invalidUrl, (err) => { + expect(err).toMatchObject({ + message: '`url` argument is not a string or URL.', + }) + }) + }) +}) + function createCookie( cookieString: string, options: { diff --git a/lib/cookie/cookie.ts b/lib/cookie/cookie.ts index 30733fdd..5c33ea6c 100644 --- a/lib/cookie/cookie.ts +++ b/lib/cookie/cookie.ts @@ -71,7 +71,6 @@ function parseCookiePair( looseMode: boolean, ): Cookie | undefined { cookiePair = trimTerminator(cookiePair) - validators.validate(validators.isString(cookiePair), cookiePair) let firstEq = cookiePair.indexOf('=') if (looseMode) { diff --git a/lib/cookie/cookieCompare.ts b/lib/cookie/cookieCompare.ts index 97a03941..2a110950 100644 --- a/lib/cookie/cookieCompare.ts +++ b/lib/cookie/cookieCompare.ts @@ -1,5 +1,3 @@ -import { safeToString } from '../utils' -import * as validators from '../validators' import type { Cookie } from './cookie' /** @@ -65,8 +63,6 @@ const MAX_TIME = 2147483647000 * @public */ export function cookieCompare(a: Cookie, b: Cookie): number { - validators.validate(validators.isObject(a), safeToString(a)) - validators.validate(validators.isObject(b), safeToString(b)) let cmp: number // descending for length: b CMP a diff --git a/lib/cookie/cookieJar.ts b/lib/cookie/cookieJar.ts index 07cae3b8..8dddf41e 100644 --- a/lib/cookie/cookieJar.ts +++ b/lib/cookie/cookieJar.ts @@ -206,7 +206,6 @@ function getCookieContext(url: unknown): URL | urlParse { type SameSiteLevel = keyof (typeof Cookie)['sameSiteLevel'] function checkSameSiteContext(value: string): SameSiteLevel | undefined { - validators.validate(validators.isNonEmptyString(value), value) const context = String(value).toLowerCase() if (context === 'none' || context === 'lax' || context === 'strict') { return context @@ -223,7 +222,6 @@ function checkSameSiteContext(value: string): SameSiteLevel | undefined { * @returns boolean */ function isSecurePrefixConditionMet(cookie: Cookie): boolean { - validators.validate(validators.isObject(cookie), safeToString(cookie)) const startsWithSecurePrefix = typeof cookie.key === 'string' && cookie.key.startsWith('__Secure-') return !startsWithSecurePrefix || cookie.secure @@ -241,7 +239,6 @@ function isSecurePrefixConditionMet(cookie: Cookie): boolean { * @returns boolean */ function isHostPrefixConditionMet(cookie: Cookie): boolean { - validators.validate(validators.isObject(cookie)) const startsWithHostPrefix = typeof cookie.key === 'string' && cookie.key.startsWith('__Host-') return ( @@ -330,12 +327,16 @@ export class CookieJar { } let syncErr: Error | null = null let syncResult: T | undefined = undefined - fn.call(this, (error: Error | null, result?: T | undefined) => { - syncErr = error - syncResult = result - }) - // These seem to be false positives; it can't detect that the value may be changed in the callback - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, @typescript-eslint/only-throw-error + + try { + fn.call(this, (error: Error | null, result?: T | undefined) => { + syncErr = error + syncResult = result + }) + } catch (err) { + syncErr = err as Error + } + if (syncErr) throw syncErr return syncResult @@ -436,41 +437,45 @@ export class CookieJar { } const promiseCallback = createPromiseCallback(callback) const cb = promiseCallback.callback + let context - if (typeof url === 'string') { - validators.validate( - validators.isNonEmptyString(url), - callback, - safeToString(options), - ) - } - - const context = getCookieContext(url) + try { + if (typeof url === 'string') { + validators.validate( + validators.isNonEmptyString(url), + callback, + safeToString(options), + ) + } - let err + context = getCookieContext(url) - if (typeof url === 'function') { - return promiseCallback.reject(new Error('No URL was specified')) - } + if (typeof url === 'function') { + return promiseCallback.reject(new Error('No URL was specified')) + } - if (typeof options === 'function') { - options = defaultSetCookieOptions - } + if (typeof options === 'function') { + options = defaultSetCookieOptions + } - validators.validate(typeof cb === 'function', cb) + validators.validate(typeof cb === 'function', cb) - if ( - !validators.isNonEmptyString(cookie) && - !validators.isObject(cookie) && - cookie instanceof String && - cookie.length == 0 - ) { - return promiseCallback.resolve(undefined) + if ( + !validators.isNonEmptyString(cookie) && + !validators.isObject(cookie) && + cookie instanceof String && + cookie.length == 0 + ) { + return promiseCallback.resolve(undefined) + } + } catch (err) { + return promiseCallback.reject(err as Error) } const host = canonicalDomain(context.hostname) ?? null const loose = options?.loose || this.enableLooseMode + let err let sameSiteContext = null if (options?.sameSiteContext) { sameSiteContext = checkSameSiteContext(options.sameSiteContext) @@ -731,6 +736,18 @@ export class CookieJar { return this.callSync(setCookieFn) } + /** + * Retrieve the list of cookies that can be sent in a Cookie header for the + * current URL. + * + * @remarks + * - The array of cookies returned will be sorted according to {@link cookieCompare}. + * + * - The {@link Cookie.lastAccessed} property will be updated on all returned cookies. + * + * @param url - The domain to store the cookie with. + */ + getCookies(url: string): Promise /** * Retrieve the list of cookies that can be sent in a Cookie header for the * current URL. @@ -803,13 +820,25 @@ export class CookieJar { } const promiseCallback = createPromiseCallback(callback) const cb = promiseCallback.callback + let context + + try { + if (typeof url === 'string') { + validators.validate(validators.isNonEmptyString(url), cb, url) + } + + context = getCookieContext(url) - if (typeof url === 'string') { - validators.validate(validators.isNonEmptyString(url), cb, url) + validators.validate( + validators.isObject(options), + cb, + safeToString(options), + ) + + validators.validate(typeof cb === 'function', cb) + } catch (parameterError) { + return promiseCallback.reject(parameterError as Error) } - const context = getCookieContext(url) - validators.validate(validators.isObject(options), cb, safeToString(options)) - validators.validate(typeof cb === 'function', cb) const host = canonicalDomain(context.hostname) const path = context.pathname || '/' @@ -1147,9 +1176,7 @@ export class CookieJar { */ serialize(callback?: Callback): unknown { const promiseCallback = createPromiseCallback(callback) - const cb = promiseCallback.callback - validators.validate(typeof cb === 'function', cb) let type: string | null = this.store.constructor.name if (validators.isObject(type)) { type = null diff --git a/lib/cookie/formatDate.ts b/lib/cookie/formatDate.ts index 4c5ecfc0..c8650628 100644 --- a/lib/cookie/formatDate.ts +++ b/lib/cookie/formatDate.ts @@ -1,6 +1,3 @@ -import * as validators from '../validators' -import { safeToString } from '../utils' - /** * Format a {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date | Date} into * the {@link https://www.rfc-editor.org/rfc/rfc2616#section-3.3.1 | preferred Internet standard format} @@ -16,6 +13,5 @@ import { safeToString } from '../utils' * @public */ export function formatDate(date: Date): string { - validators.validate(validators.isDate(date), safeToString(date)) return date.toUTCString() } diff --git a/lib/cookie/permutePath.ts b/lib/cookie/permutePath.ts index 4574b9ec..d56b1a1a 100644 --- a/lib/cookie/permutePath.ts +++ b/lib/cookie/permutePath.ts @@ -1,5 +1,3 @@ -import * as validators from '../validators' - /** * Generates the permutation of all possible values that {@link pathMatch} the `path` parameter. * The array is in longest-to-shortest order. Useful when building custom {@link Store} implementations. @@ -14,7 +12,6 @@ import * as validators from '../validators' * @public */ export function permutePath(path: string): string[] { - validators.validate(validators.isString(path)) if (path === '/') { return ['/'] } diff --git a/test/cookie_jar_test.js b/test/cookie_jar_test.js index a4191d22..7899eb6d 100644 --- a/test/cookie_jar_test.js +++ b/test/cookie_jar_test.js @@ -780,7 +780,8 @@ vows topic: function() { const jar = new tough.CookieJar(); jar.setCookie( - new String("x=y; Domain=example.com; Path=/"), + undefined, + undefined, this.callback ); },