/** * Provides a iterable map interfaces for managing cookies server side. * * @example * To access the keys in a request and have any set keys available for creating * a response: * * ```ts * import { * CookieMap, * mergeHeaders * } from "https://deno.land/std@$STD_VERSION/http/unstable_cookie_map.ts"; * * const request = new Request("https://localhost/", { * headers: { "cookie": "foo=bar; bar=baz;"} * }); * * const cookies = new CookieMap(request, { secure: true }); * console.log(cookies.get("foo")); // logs "bar" * cookies.set("session", "1234567", { secure: true }); * * const response = new Response("hello", { * headers: mergeHeaders({ * "content-type": "text/plain", * }, cookies), * }); * ``` * * @example * To have automatic management of cryptographically signed cookies, you can use * the {@linkcode SecureCookieMap} instead of {@linkcode CookieMap}. The biggest * difference is that the methods operate async in order to be able to support * async signing and validation of cookies: * * ```ts * import { * SecureCookieMap, * mergeHeaders, * type KeyRing, * } from "https://deno.land/std@$STD_VERSION/http/unstable_cookie_map.ts"; * * const request = new Request("https://localhost/", { * headers: { "cookie": "foo=bar; bar=baz;"} * }); * * // The keys must implement the `KeyRing` interface. * declare const keys: KeyRing; * * const cookies = new SecureCookieMap(request, { keys, secure: true }); * console.log(await cookies.get("foo")); // logs "bar" * // the cookie will be automatically signed using the supplied key ring. * await cookies.set("session", "1234567"); * * const response = new Response("hello", { * headers: mergeHeaders({ * "content-type": "text/plain", * }, cookies), * }); * ``` * * In addition, if you have a {@linkcode Response} or {@linkcode Headers} for a * response at construction of the cookies object, they can be passed and any * set cookies will be added directly to those headers: * * ```ts * import { CookieMap } from "https://deno.land/std@$STD_VERSION/http/unstable_cookie_map.ts"; * * const request = new Request("https://localhost/", { * headers: { "cookie": "foo=bar; bar=baz;"} * }); * * const response = new Response("hello", { * headers: { "content-type": "text/plain" }, * }); * * const cookies = new CookieMap(request, { response }); * console.log(cookies.get("foo")); // logs "bar" * cookies.set("session", "1234567"); * ``` * * @module */ import * as dntShim from "../../../../_dnt.shims.js"; export interface CookieMapOptions { /** The {@linkcode Response} or the headers that will be used with the * response. When provided, `Set-Cookie` headers will be set in the headers * when cookies are set or deleted in the map. * * An alternative way to extract the headers is to pass the cookie map to the * {@linkcode mergeHeaders} function to merge various sources of the * headers to be provided when creating or updating a response. */ response?: Headered | dntShim.Headers; /** A flag that indicates if the request and response are being handled over * a secure (e.g. HTTPS/TLS) connection. * * @default {false} */ secure?: boolean; } export interface CookieMapSetDeleteOptions { /** The domain to scope the cookie for. */ domain?: string; /** When the cookie expires. */ expires?: Date; /** Number of seconds until the cookie expires */ maxAge?: number; /** A flag that indicates if the cookie is valid over HTTP only. */ httpOnly?: boolean; /** Do not error when signing and validating cookies over an insecure * connection. */ ignoreInsecure?: boolean; /** Overwrite an existing value. */ overwrite?: boolean; /** The path the cookie is valid for. */ path?: string; /** Override the flag that was set when the instance was created. */ secure?: boolean; /** Set the same-site indicator for a cookie. */ sameSite?: "strict" | "lax" | "none" | boolean; } /** * An object which contains a `headers` property which has a value of an * instance of {@linkcode Headers}, like {@linkcode Request} and * {@linkcode Response}. */ export interface Headered { headers: dntShim.Headers; } export interface Mergeable { [cookieMapHeadersInitSymbol](): [string, string][]; } export interface SecureCookieMapOptions { /** Keys which will be used to validate and sign cookies. The key ring should * implement the {@linkcode KeyRing} interface. */ keys?: KeyRing; /** The {@linkcode Response} or the headers that will be used with the * response. When provided, `Set-Cookie` headers will be set in the headers * when cookies are set or deleted in the map. * * An alternative way to extract the headers is to pass the cookie map to the * {@linkcode mergeHeaders} function to merge various sources of the * headers to be provided when creating or updating a response. */ response?: Headered | dntShim.Headers; /** A flag that indicates if the request and response are being handled over * a secure (e.g. HTTPS/TLS) connection. * * @default {false} */ secure?: boolean; } export interface SecureCookieMapGetOptions { /** Overrides the flag that was set when the instance was created. */ signed?: boolean; } export interface SecureCookieMapSetDeleteOptions { /** The domain to scope the cookie for. */ domain?: string; /** When the cookie expires. */ expires?: Date; /** Number of seconds until the cookie expires */ maxAge?: number; /** A flag that indicates if the cookie is valid over HTTP only. */ httpOnly?: boolean; /** Do not error when signing and validating cookies over an insecure * connection. */ ignoreInsecure?: boolean; /** Overwrite an existing value. */ overwrite?: boolean; /** The path the cookie is valid for. */ path?: string; /** Override the flag that was set when the instance was created. */ secure?: boolean; /** Set the same-site indicator for a cookie. */ sameSite?: "strict" | "lax" | "none" | boolean; /** Override the default behavior of signing the cookie. */ signed?: boolean; } /** * Symbol which is used in {@link mergeHeaders} to extract a * `[string | string][]` from an instance to generate the final set of * headers. */ export declare const cookieMapHeadersInitSymbol: unique symbol; /** * Allows merging of various sources of headers into a final set of headers * which can be used in a {@linkcode Response}. * * Note, that unlike when passing a `Response` or {@linkcode Headers} used in a * response to {@linkcode CookieMap} or {@linkcode SecureCookieMap}, merging * will not ensure that there are no other `Set-Cookie` headers from other * sources, it will simply append the various headers together. */ export declare function mergeHeaders(...sources: (Headered | dntShim.HeadersInit | Mergeable)[]): dntShim.Headers; declare const keys: unique symbol; declare const requestHeaders: unique symbol; declare const responseHeaders: unique symbol; declare const isSecure: unique symbol; declare const requestKeys: unique symbol; /** An internal abstract class which provides common functionality for * {@link CookieMap} and {@link SecureCookieMap}. */ declare abstract class CookieMapBase implements Mergeable { [keys]?: string[]; [requestHeaders]: dntShim.Headers; [responseHeaders]: dntShim.Headers; [isSecure]: boolean; [requestKeys](): string[]; constructor(request: dntShim.Headers | Headered, options: CookieMapOptions); /** A method used by {@linkcode mergeHeaders} to be able to merge * headers from various sources when forming a {@linkcode Response}. */ [cookieMapHeadersInitSymbol](): [string, string][]; } /** * Provides a way to manage cookies in a request and response on the server * as a single iterable collection. * * The methods and properties align to {@linkcode Map}. When constructing a * {@linkcode Request} or {@linkcode Headers} from the request need to be * provided, as well as optionally the {@linkcode Response} or `Headers` for the * response can be provided. Alternatively the {@linkcode mergeHeaders} * function can be used to generate a final set of headers for sending in the * response. */ export declare class CookieMap extends CookieMapBase { /** Contains the number of valid cookies in the request headers. */ get size(): number; constructor(request: dntShim.Headers | Headered, options?: CookieMapOptions); /** Deletes all the cookies from the {@linkcode Request} in the response. */ clear(options?: CookieMapSetDeleteOptions): void; /** Set a cookie to be deleted in the response. * * This is a convenience function for `set(key, null, options?)`. */ delete(key: string, options?: CookieMapSetDeleteOptions): boolean; /** Return the value of a matching key present in the {@linkcode Request}. If * the key is not present `undefined` is returned. */ get(key: string): string | undefined; /** Returns `true` if the matching key is present in the {@linkcode Request}, * otherwise `false`. */ has(key: string): boolean; /** Set a named cookie in the response. The optional * {@linkcode CookieMapSetDeleteOptions} are applied to the cookie being set. */ set(key: string, value: string | null, options?: CookieMapSetDeleteOptions): this; /** Iterate over the cookie keys and values that are present in the * {@linkcode Request}. This is an alias of the `[Symbol.iterator]` method * present on the class. */ entries(): IterableIterator<[string, string]>; /** Iterate over the cookie keys that are present in the * {@linkcode Request}. */ keys(): IterableIterator; /** Iterate over the cookie values that are present in the * {@linkcode Request}. */ values(): IterableIterator; /** Iterate over the cookie keys and values that are present in the * {@linkcode Request}. */ [Symbol.iterator](): IterableIterator<[string, string]>; } /** * Types of data that can be signed cryptographically. */ export type Data = string | number[] | ArrayBuffer | Uint8Array; /** * An interface which describes the methods that {@linkcode SecureCookieMap} * uses to sign and verify cookies. */ export interface KeyRing { /** Given a set of data and a digest, return the key index of the key used * to sign the data. The index is 0 based. A non-negative number indices the * digest is valid and a key was found. */ indexOf(data: Data, digest: string): Promise | number; /** Sign the data, returning a string based digest of the data. */ sign(data: Data): Promise | string; /** Verifies the digest matches the provided data, indicating the data was * signed by the keyring and has not been tampered with. */ verify(data: Data, digest: string): Promise | boolean; } /** * Provides an way to manage cookies in a request and response on the server * as a single iterable collection, as well as the ability to sign and verify * cookies to prevent tampering. * * The methods and properties align to {@linkcode Map}, but due to the need to * support asynchronous cryptographic keys, all the APIs operate async. When * constructing a {@linkcode Request} or {@linkcode Headers} from the request * need to be provided, as well as optionally the {@linkcode Response} or * `Headers` for the response can be provided. Alternatively the * {@linkcode mergeHeaders} function can be used to generate a final set * of headers for sending in the response. * * On construction, the optional set of keys implementing the * {@linkcode KeyRing} interface. While it is optional, if you don't plan to use * keys, you might want to consider using just the {@linkcode CookieMap}. */ export declare class SecureCookieMap extends CookieMapBase { #private; /** Is set to a promise which resolves with the number of cookies in the * {@linkcode Request}. */ get size(): Promise; constructor(request: dntShim.Headers | Headered, options?: SecureCookieMapOptions); /** Sets all cookies in the {@linkcode Request} to be deleted in the * response. */ clear(options: SecureCookieMapSetDeleteOptions): Promise; /** Set a cookie to be deleted in the response. * * This is a convenience function for `set(key, null, options?)`. */ delete(key: string, options?: SecureCookieMapSetDeleteOptions): Promise; /** Get the value of a cookie from the {@linkcode Request}. * * If the cookie is signed, and the signature is invalid, `undefined` will be * returned and the cookie will be set to be deleted in the response. If the * cookie is using an "old" key from the keyring, the cookie will be re-signed * with the current key and be added to the response to be updated. */ get(key: string, options?: SecureCookieMapGetOptions): Promise; /** Returns `true` if the key is in the {@linkcode Request}. * * If the cookie is signed, and the signature is invalid, `false` will be * returned and the cookie will be set to be deleted in the response. If the * cookie is using an "old" key from the keyring, the cookie will be re-signed * with the current key and be added to the response to be updated. */ has(key: string, options?: SecureCookieMapGetOptions): Promise; /** Set a cookie in the response headers. * * If there was a keyring set, cookies will be automatically signed, unless * overridden by the passed options. Cookies can be deleted by setting the * value to `null`. */ set(key: string, value: string | null, options?: SecureCookieMapSetDeleteOptions): Promise; /** Iterate over the {@linkcode Request} cookies, yielding up a tuple * containing the key and value of each cookie. * * If a key ring was provided, only properly signed cookie keys and values are * returned. */ entries(): AsyncIterableIterator<[string, string]>; /** Iterate over the request's cookies, yielding up the key of each cookie. * * If a keyring was provided, only properly signed cookie keys are * returned. */ keys(): AsyncIterableIterator; /** Iterate over the request's cookies, yielding up the value of each cookie. * * If a keyring was provided, only properly signed cookie values are * returned. */ values(): AsyncIterableIterator; /** Iterate over the {@linkcode Request} cookies, yielding up a tuple * containing the key and value of each cookie. * * If a key ring was provided, only properly signed cookie keys and values are * returned. */ [Symbol.asyncIterator](): AsyncIterableIterator<[string, string]>; } export {};