{"version":3,"sources":["jsdelivr-header.js","/npm/request-http-cache@1.1.0/lib/index.js"],"names":[],"mappings":"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","file":"/npm/request-http-cache@1.1.0/lib/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/request-http-cache@1.1.0/lib/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","'use strict';\n\nvar _ = require('lodash');\nvar debug = require('debug')('http-cache:cache');\nvar RedisBackend = require('./redis-backend');\nvar InMemoryBackend = require('./inmemory-backend');\nvar keyGenerator = require('./key-generator');\nvar Wreck = require('@hapi/wreck');\nvar mockStats = require('./mock-stats');\n\nfunction getBackend(options) {\n  if (options.backend === 'redis') {\n    return new RedisBackend(options);\n  }\n\n  return new InMemoryBackend(options);\n}\n\nfunction HttpCache(options) {\n  if (!options) options = {};\n  this.stats = options.stats || mockStats;\n  this.backend = options.backend && typeof options.backend === 'object' ? options.backend : getBackend(options);\n  this.extension = this.extensionMethod.bind(this);\n}\n\nHttpCache.prototype = {\n  extensionMethod: function(options, callback, next) {\n    var method = options.method ? options.method.toUpperCase() : 'GET'; /* default is GET */\n    /* Only for GET */\n    if (method !== 'GET' || options.disableCache) {\n      return next(options, callback);\n    }\n\n    this._fetchWithCache(options, callback, next);\n  },\n\n  _fetchWithCache: function(options, callback, next) {\n    var self = this;\n    var requestStartTime = Date.now();\n\n    var requestUrl = options.uri || options.url;\n\n    this.backend.getVaryHeaders(requestUrl, function(err, varyHeaders) {\n      if (err) {\n        /* WARN */\n        debug('http.cache error looking up headers: ' + err, { exception: err});\n        self.stats.increment('backend.error');\n      }\n\n      /* Vary headers of '' means that we know there are no vary headers */\n      if (!err && (varyHeaders || varyHeaders === '')) {\n        debug('vary headers available: ' + varyHeaders);\n        return self._cacheLookup(requestUrl, varyHeaders, options, requestStartTime, callback, next);\n      }\n\n      /** We don't have vary headers, proceed with a full request */\n      return self._makeRequest(requestUrl, options, null, null, requestStartTime, callback, next);\n    });\n  },\n\n  /**\n   * Proceed with a cache lookup, given a request and a set of Vary headers\n   */\n  _cacheLookup: function(requestUrl, varyHeaders, options, requestStartTime, callback, next) {\n    var self = this;\n    var key = keyGenerator(requestUrl, options.headers, varyHeaders);\n    debug('cache lookup key is: ' + key);\n\n    this.backend.getEtagExpiry(key, function(err, etagExpiry) {\n      if (err) {\n        /* WARN */\n        debug('http.cache error: ' + err, { exception: err});\n        self.stats.increment('backend.error');\n        /* Continue with the request regardless */\n      }\n\n      // The key is hash, so beware of duplicates\n      if (etagExpiry && requestUrl !== etagExpiry.url) {\n        // Duplicate key, ignore\n        etagExpiry = null;\n      }\n\n      if (etagExpiry) {\n        var fresh = etagExpiry.expiry && etagExpiry.expiry >= Date.now();\n\n        /**\n         * If the content is fresh, return it immediately without hitting the endpoint\n         */\n        if (fresh) {\n          return self._getContent(requestUrl, key, function(err2, cachedContent) {\n            /* No need to report error as _getContent does it */\n\n            if (err2 || !cachedContent) return self._makeRequest(requestUrl, options, key, null, requestStartTime, callback, next);\n\n            return self._doSuccessCallback(options, cachedContent, function(err, _response, _body) {\n              if (err) {\n                /* WARN */\n                debug('Error parsing cache content: ' + err, { exception: err });\n\n                /* Make the request again */\n                return self._makeRequest(requestUrl, options, key, null, requestStartTime, callback, next);\n              }\n\n              debug('Cache hit for %s', requestUrl);\n              self.stats.increment(['hit', 'hit.fresh']);\n\n              if (cachedContent.backendResponseTime) {\n                var responseTime = Date.now() - requestStartTime;\n                self.stats.timing('response.time.saved',  cachedContent.backendResponseTime - responseTime);\n              }\n\n              return callback(null, _response, _body);\n            });\n          });\n        }\n      }\n\n      return self._makeRequest(requestUrl, options, key, etagExpiry, requestStartTime, callback, next);\n    });\n  },\n\n  /**\n   * Make an HTTP request to the underlying request object\n   */\n  _makeRequest: function(requestUrl, options, key, etagExpiry, requestStartTime, callback, next) {\n    var self = this;\n    var etag = etagExpiry && etagExpiry.etag;\n    var originalOptions = options;\n\n    /* If we have an etag, always use it */\n    if (etag) {\n      /* Clone the options so not to modify the original */\n      options = _.extend({}, options);\n      options.headers = _.extend({}, options.headers, {\n        'If-None-Match': etag\n      });\n    }\n\n    next(options, function(err, response, body) {\n      if (err || (response.statusCode >= 500 && response.statusCode < 600)) {\n        if (etagExpiry) {\n          /* WARN */\n          debug('http.cache upstream failure. Using cached response: ' + err, { exception: err});\n\n          return self._getContent(requestUrl, key, function(_err, cachedContent) {\n            /* No need to report error as _getContent does it */\n\n            if (_err || !cachedContent) return callback(err, response, body); // Unable to lookup content\n\n            return self._doSuccessCallback(options, cachedContent, function(_err, _response, _body) {\n              if (_err) {\n                /* TODO: delete the bad content ... */\n                debug('Error parsing cache content: ' + _err, { exception: _err });\n                /* Return with the original error, response, body */\n                return callback(err, response, body);\n              }\n\n              self.stats.increment('hit.failback');\n\n              if (cachedContent.backendResponseTime) {\n                var responseTime = Date.now() - requestStartTime;\n                self.stats.timing('response.time.saved',  cachedContent.backendResponseTime - responseTime);\n              }\n\n              return callback(null, _response, _body);\n            });\n          });\n        } else {\n          return callback(err, response, body);\n        }\n\n        return;\n      }\n\n      if (etag && response.statusCode === 304) {\n        debug('Conditional request success. Attempting to use cached content');\n\n        return self._getContent(requestUrl, key, function(err, cachedContent) {\n          /* No need to report error as _getContent does it */\n\n          /* Corrupted data - reissue the request without the cache */\n          if (err || !cachedContent) return self._makeRequest(requestUrl, originalOptions, key, null, requestStartTime, callback, next);\n\n          return self._doSuccessCallback(options, cachedContent, function(err, _response, _body) {\n            if (err) {\n              /* WARN */\n              debug('Error parsing cache content: ' + err, { exception: err });\n              return self._makeRequest(requestUrl, originalOptions, key, null, requestStartTime, callback, next);\n            }\n\n            if (response.headers['cache-control']) {\n              var cacheHeader = Wreck.parseCacheControl(response.headers['cache-control']);\n              var expiry = Date.now();\n              if (cacheHeader && cacheHeader['max-age']) {\n                expiry += cacheHeader['max-age'] * 1000;\n              }\n\n              debug('Updating expiry');\n              /* Safe to use key here as we cannot get this far without key being set */\n              self.backend.updateExpiry(requestUrl, key, expiry, function(err) {\n                if (err) {\n                  debug('Unable to update expiry for content: ' + err, { exception: err });\n                }\n              });\n            }\n\n            self.stats.increment(['hit', 'hit.cond']);\n\n            if (cachedContent.backendResponseTime) {\n              var responseTime = Date.now() - requestStartTime;\n              self.stats.timing('response.time.saved',  cachedContent.backendResponseTime - responseTime);\n            }\n\n            return callback(null, _response, _body);\n          });\n        });\n      }\n\n      self.stats.increment('miss');\n\n      if (response.headers) {\n        var responseEtag = response.headers.etag;\n\n        if (response.headers['cache-control']) {\n          var cacheHeader = Wreck.parseCacheControl(response.headers['cache-control']);\n          var expiry = Date.now();\n          if (cacheHeader && cacheHeader['max-age']) {\n            expiry += cacheHeader['max-age'] * 1000;\n          }\n\n          if (responseEtag && response.statusCode === 200) {\n            /* Store the cache response async */\n            self._storeResponse(requestUrl, options.headers, response, expiry, responseEtag, body, requestStartTime, function(err) {\n              if (err) {\n                /* WARN */\n                debug('http.cache cache storage failure: ' + err, { exception: err});\n                self.stats.increment('backend.error');\n              }\n            });\n          }\n        }\n      }\n\n      callback(null, response, body);\n    });\n\n  },\n\n  /**\n   * Fetch the content from the backend and confirm that the URL matches\n   */\n  _getContent: function(url, key, callback) {\n    var self = this;\n    if (!key) return callback();\n\n    this.backend.getContent(key, function(err, cachedContent) {\n      if (err) {\n        /* WARN */\n        debug('Error looking up content: ' + err, { exception: err });\n        self.stats.increment('backend.error');\n      }\n\n      /* Corrupted data - reissue the request without the cache */\n      if (err || !cachedContent) return callback();\n\n      /* Confirm that the URL for the cached content matches */\n      if (cachedContent.url !== url) {\n        debug('Cache hashing collision: ' + url + \", vs \" + cachedContent.url);\n        return callback();\n      }\n\n      return callback(null, cachedContent);\n    });\n  },\n\n  _storeResponse: function(requestUrl, requestHeaders, response, expiry, etag, body, requestStartTime, callback) {\n    var vary = response.headers.vary;\n    var backendResponseTime = Date.now() - requestStartTime;\n    /* Regenerate the key using the new vary header */\n    var key = keyGenerator(requestUrl, requestHeaders, vary);\n\n    this.backend.store(key, {\n        url: requestUrl,\n        statusCode: response.statusCode,\n        etag: etag,\n        expiry: expiry,\n        headers: response.headers,\n        body: body,\n        backendResponseTime: backendResponseTime\n      }, callback);\n  },\n\n  /**\n   * Converts the cachedContent into a request style callback\n   */\n  _doSuccessCallback: function(options, cachedContent, callback) {\n    var response = {\n      statusCode: parseInt(cachedContent.statusCode, 10),\n      headers: cachedContent.headers\n    };\n\n    if (options.json) {\n      /* Use the cached response */\n      try {\n        var parsed = JSON.parse(cachedContent.body);\n        return callback(null, response, parsed);\n      } catch(e) {\n        this.stats.increment('json.parse.error');\n        return callback(e);\n      }\n    }\n\n    /* Use the cached response */\n    return callback(null, response, cachedContent.body);\n  }\n};\n\n\nmodule.exports = HttpCache;\nmodule.exports.backends = {\n  InMemory: InMemoryBackend,\n  Redis: RedisBackend\n};\n"]}