UNPKG

@hugoalh/http-header-retry-after

Version:

A module to handle the HTTP header `Retry-After` according to the specification RFC 9110.

97 lines (96 loc) 2.77 kB
const regexpDateRFC7231 = /^[A-Z][a-z][a-z], \d\d [A-Z][a-z][a-z] \d\d\d\d \d\d:\d\d:\d\d GMT$/; const regexpDecimalInteger = /^\d+$/; /** * Handle the HTTP header `Retry-After` according to the specification RFC 9110. */ export class HTTPHeaderRetryAfter { get [Symbol.toStringTag]() { return "HTTPHeaderRetryAfter"; } #timestamp; /** * Initialize. * @param {number | string | Date | Headers | Response} input Input. */ constructor(input) { if (typeof input === "number") { if (!(input >= 0 && input <= Number.MAX_SAFE_INTEGER)) { throw new RangeError(`Parameter \`input\` is not a number which is positive and safe!`); } this.#timestamp = new Date(Date.now() + input * 1000); } else if (input instanceof Date) { this.#timestamp = new Date(input); } else { let inputFmt; if (input instanceof Response) { inputFmt = input.headers.get("Retry-After") ?? "0"; } else if (input instanceof Headers) { inputFmt = input.get("Retry-After") ?? "0"; } else { inputFmt = input; } if (regexpDateRFC7231.test(inputFmt)) { this.#timestamp = new Date(inputFmt); } else if (regexpDecimalInteger.test(inputFmt)) { this.#timestamp = new Date(Date.now() + Number(inputFmt) * 1000); } else { throw new SyntaxError(`\`${inputFmt}\` is not a valid HTTP header \`Retry-After\` value!`); } } } /** * Get `Date`. * @returns {Date} */ getDate() { return new Date(this.#timestamp); } /** * Get remain time in milliseconds. * @returns {number} */ getRemainTimeMilliseconds() { return Math.max(0, this.#timestamp.valueOf() - Date.now()); } /** * Get remain time in seconds. * @returns {number} */ getRemainTimeSeconds() { return (this.getRemainTimeMilliseconds() / 1000); } /** * Stringify. * @returns {string} */ stringify() { return this.toString(); } /** * Convert to string. * @returns {string} */ toString() { return this.#timestamp.toUTCString(); } /** * Initialize in safe way. * @param {number | string | Date | Headers | Response} input Input. * @returns {HTTPHeaderRetryAfter | null} */ static parseSafe(input) { try { return new this(input); } catch { return null; } } } export default HTTPHeaderRetryAfter;