* @see https://www.rfc-editor.org/rfc/rfc9111.html#name-storing-responses-to-authen * * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions['type']} cacheType * @param {number} statusCode * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders * @param
(cacheType, statusCode, resHeaders, cacheControlDirectives, reqHeaders)
| 490 | * @param {import('../../types/header.d.ts').IncomingHttpHeaders} [reqHeaders] |
| 491 | */ |
| 492 | function canCacheResponse (cacheType, statusCode, resHeaders, cacheControlDirectives, reqHeaders) { |
| 493 | // Status code must be final and understood. |
| 494 | if (statusCode < 200 || arrayIncludes(NOT_UNDERSTOOD_STATUS_CODES, statusCode)) { |
| 495 | return false |
| 496 | } |
| 497 | // Responses with neither status codes that are heuristically cacheable, nor "explicit enough" caching |
| 498 | // directives, are not cacheable. "Explicit enough": see https://www.rfc-editor.org/rfc/rfc9111.html#section-3 |
| 499 | if (!arrayIncludes(HEURISTICALLY_CACHEABLE_STATUS_CODES, statusCode) && !resHeaders['expires'] && |
| 500 | !cacheControlDirectives.public && |
| 501 | cacheControlDirectives['max-age'] === undefined && |
| 502 | // RFC 9111: a private response directive, if the cache is not shared |
| 503 | !(cacheControlDirectives.private && cacheType === 'private') && |
| 504 | !(cacheControlDirectives['s-maxage'] !== undefined && cacheType === 'shared') |
| 505 | ) { |
| 506 | return false |
| 507 | } |
| 508 | |
| 509 | if (cacheControlDirectives['no-store']) { |
| 510 | return false |
| 511 | } |
| 512 | |
| 513 | if (cacheType === 'shared' && cacheControlDirectives.private === true) { |
| 514 | return false |
| 515 | } |
| 516 | |
| 517 | // https://www.rfc-editor.org/rfc/rfc9111.html#section-4.1-5 |
| 518 | if (resHeaders.vary && hasVaryStar(resHeaders.vary)) { |
| 519 | return false |
| 520 | } |
| 521 | |
| 522 | // https://www.rfc-editor.org/rfc/rfc9111.html#name-storing-responses-to-authen |
| 523 | if (reqHeaders != null && Object.hasOwn(reqHeaders, 'authorization')) { |
| 524 | if ( |
| 525 | !cacheControlDirectives.public && |
| 526 | !cacheControlDirectives['s-maxage'] && |
| 527 | !cacheControlDirectives['must-revalidate'] |
| 528 | ) { |
| 529 | return false |
| 530 | } |
| 531 | |
| 532 | if (typeof reqHeaders.authorization !== 'string') { |
| 533 | return false |
| 534 | } |
| 535 | |
| 536 | if ( |
| 537 | Array.isArray(cacheControlDirectives['no-cache']) && |
| 538 | arrayIncludes(cacheControlDirectives['no-cache'], 'authorization') |
| 539 | ) { |
| 540 | return false |
| 541 | } |
| 542 | |
| 543 | if ( |
| 544 | Array.isArray(cacheControlDirectives['private']) && |
| 545 | arrayIncludes(cacheControlDirectives['private'], 'authorization') |
| 546 | ) { |
| 547 | return false |
| 548 | } |
| 549 | } |
no test coverage detected