コード例 #1
0
ファイル: index.js プロジェクト: jimlambie/web
Cache.prototype.cachingEnabled = function (req) {
  // Check it is not a json view
  var query = url.parse(req.url, true).query
  if (query.json && query.json !== 'false') return false

  // Disable cache for debug mode
  if (config.get('debug')) return false

  // if it's in the endpoint and caching is enabled
  var endpoint = this.getEndpoint(req)

  if (endpoint) {
    this.options.cache =
      typeof endpoint.page.settings.cache !== 'undefined'
        ? endpoint.page.settings.cache
        : this.enabled

    return this.enabled && this.options.cache
  } else {
    // Otherwise it might be in the public folder
    var file = url.parse(req.url).pathname

    return compressible(mime.lookup(file))
  }
}
コード例 #2
0
 function shouldCompress(req, res) {
   var type = res.getHeader('Content-Type');
   if (type === undefined || !compressible(type)) {
     debug('%s not compressible', type);
     return false;
   }
   return true;
 }
コード例 #3
0
ファイル: index.js プロジェクト: reem/cash
  return function* cash(next) {
    this.vary('Accept-Encoding')
    this.cashed = cashed

    yield* next

    // check for HTTP caching just in case
    if (!this.cash) {
      if (this.request.fresh) this.response.status = 304
      return
    }

    // cache the response

    // only cache GET/HEAD 200s
    if (this.response.status !== 200) return
    if (!methods[this.request.method]) return
    var body = this.response.body
    if (!body) return

    // stringify JSON bodies
    if (isJSON(body)) body = this.response.body = JSON.stringify(body)
    // buffer streams
    if (typeof body.pipe === 'function') {
      // note: non-binary streams are NOT supported!
      body = this.response.body = Buffer.concat(yield toArray(body))
    }

    // avoid any potential errors with middleware ordering
    if (this.response.get('Content-Encoding') || 'identity' !== 'identity') {
      throw new Error('Place koa-cache below any compression middleware.')
    }

    var fresh = this.request.fresh
    if (fresh) this.response.status = 304

    var obj = {
      body: body,
      type: this.response.get('Content-Type') || null,
      lastModified: this.response.lastModified || null,
      etag: this.response.get('etag') || null,
    }

    if (compressible(obj.type) && this.response.length >= threshold) {
      obj.gzip = yield compress(body)
      if (!fresh
        && this.request.acceptsEncodings('gzip', 'identity') === 'gzip') {
        this.response.body = obj.gzip
        this.response.set('Content-Encoding', 'gzip')
      }
    }

    if (!this.response.get('Content-Encoding')) this.response.set('Content-Encoding', 'identity')

    yield set(this.cashKey, obj)
  }
コード例 #4
0
exports.filter = function filter(req, res) {
  var type = res.getHeader('Content-Type')

  if(type === undefined || !compressible(type)) {
    debug('%s not compressible', type)
    return false
  }

  return true
};
コード例 #5
0
ファイル: index.js プロジェクト: koajs/file-server
  // get the file from cache if possible
  function* get(path) {
    var val = cache[path]
    if (val && val.compress && (yield fs.exists(val.compress.path))) return val

    var stats = yield fs.stat(path).catch(ignoreStatError)
    // we don't want to cache 404s because
    // the cache object will get infinitely large
    if (!stats || !stats.isFile()) return
    stats.path = path

    var file = cache[path] = {
      stats: stats,
      etag: '"' + (yield hash(path, algorithm)).toString(encoding) + '"',
      type: mime.contentType(extname(path)) || 'application/octet-stream',
    }

    if (!compressible(file.type)) return file

    // if we can compress this file, we create a .gz
    var compress = file.compress = {
      path: path + '.gz'
    }

    // delete old .gz files in case the file has been updated
    try {
      yield fs.unlink(compress.path)
    } catch (err) {}

    // save to a random file name first
    var tmp = path + '.' + random() + '.gz'
    yield function (done) {
      fs.createReadStream(path)
      .on('error', done)
      .pipe(zlib.createGzip())
      .on('error', done)
      .pipe(fs.createWriteStream(tmp))
      .on('error', done)
      .on('finish', done)
    }

    compress.stats = yield fs.stat(tmp).catch(ignoreStatError)

    // if the gzip size is larger than the original file,
    // don't bother gzipping
    if (compress.stats.size > stats.size) {
      delete file.compress
      yield fs.unlink(tmp)
    } else {
      // otherwise, rename to the correct path
      yield fs.rename(tmp, compress.path)
    }

    return file
  }
コード例 #6
0
ファイル: gulpfile.js プロジェクト: bicealyh/cesium
function getMimeType(filename) {
    var ext = path.extname(filename);
    if (ext === '.bin' || ext === '.terrain') {
        return { type : 'application/octet-stream', compress : true };
    } else if (ext === '.md' || ext === '.glsl') {
        return { type : 'text/plain', compress : true };
    } else if (ext === '.czml' || ext === '.geojson' || ext === '.json') {
        return { type : 'application/json', compress : true };
    } else if (ext === '.js') {
        return { type : 'application/javascript', compress : true };
    } else if (ext === '.svg') {
        return { type : 'image/svg+xml', compress : true };
    } else if (ext === '.woff') {
        return { type : 'application/font-woff', compress : false };
    }

    var mimeType = mime.lookup(filename);
    return {type : mimeType, compress : compressible(mimeType)};
}
コード例 #7
0
ファイル: index.js プロジェクト: kesla/jaws
Cached.prototype.end = function (data) {
  if (data) this.write(data)
  var self = this
  var buffer = Buffer.concat(this.data)
  this.headers['content-length'] = buffer.length
  delete this.data
  this.buffer = buffer
  this.md5 = crypto.createHash('md5').update(this.buffer).digest("hex")
  this.headers['etag'] = this.md5

  if (!compressible(this.headers['content-type'])) {
    self.ended = true
    self.emit('end')
    return
  }

  zlib.gzip(buffer, function (e, compressed) {
    if (e) return self.emit('error', e)
    self.compressed = compressed
    self.ended = true
    self.emit('end')
  })

}
コード例 #8
0
ファイル: index.js プロジェクト: toajs/toa-compress
  function compress () {
    let body = this.body
    this.vary('accept-encoding')
    if (!body || this.compress === false || this.method === 'HEAD') return
    if (statuses.empty[this.response.status] || this.response.get('content-encoding')) return
    if (!(this.compress === true || compressible(this.type))) return

    let encoding = this.acceptsEncodings('gzip', 'deflate', 'identity')
    if (!encoding) this.throw(406, 'supported encodings: gzip, deflate, identity')
    if (encoding === 'identity') return

    if (!(body instanceof Stream)) {
      if (typeof body === 'string') body = Buffer.from(body)
      else if (!Buffer.isBuffer(body)) body = Buffer.from(JSON.stringify(body))
      if (body.length < threshold) return
    }

    this.set('content-encoding', encoding)
    this.remove('content-length')

    var stream = this.body = encodingMethods[encoding](options)
    if (body instanceof Stream) body.pipe(stream)
    else stream.end(body)
  }
コード例 #9
0
ファイル: index.js プロジェクト: caolinjian/FEing
  return function* staticCache(next) {
    // only accept HEAD and GET
    if (this.method !== 'HEAD' && this.method !== 'GET') return yield* next;

    // decode for `/%E4%B8%AD%E6%96%87`
    // normalize for `//index`
    var filename = safeDecodeURIComponent(path.normalize(this.path))

    var file = files[filename]

    // try to load file
    if (!file) {
      if (!options.dynamic) return yield* next
      if (path.basename(filename)[0] === '.') return yield* next
      if (filename.charAt(0) === path.sep) filename = filename.slice(1)
      try {
        var s = yield stat(path.join(dir, filename))
        if (!s.isFile()) return yield* next
      } catch (err) {
        return yield* next
      }

      file = loadFile(filename, dir, options, files)
    }

    this.status = 200

    if (enableGzip) this.vary('Accept-Encoding')

    if (!file.buffer) {
      var stats = yield stat(file.path)
      if (stats.mtime > new Date(file.mtime)) {
        file.mtime = stats.mtime.toUTCString()
        file.md5 = null
        file.length = stats.size
      }
    }

    this.response.lastModified = file.mtime
    if (file.md5) this.response.etag = file.md5

    if (this.fresh)
      return this.status = 304

    this.type = file.type
    this.length = file.zipBuffer ? file.zipBuffer.length : file.length
    this.set('Cache-Control', file.cacheControl || 'public, max-age=' + file.maxAge)
    if (file.md5) this.set('Content-MD5', file.md5)

    if (this.method === 'HEAD')
      return

    var acceptGzip = this.acceptsEncodings('gzip') === 'gzip';

    if (file.zipBuffer) {
      if (acceptGzip) {
        this.set('Content-Encoding', 'gzip')
        this.body = file.zipBuffer
      } else {
        this.body = file.buffer
      }
      return
    }

    var shouldGzip = enableGzip
      && file.length > 1024
      && acceptGzip
      && compressible(file.type)

    if (file.buffer) {
      if (shouldGzip) {

        var gzFile = files[filename + '.gz'];
        if (options.usePrecompiledGzip && gzFile && gzFile.buffer) { // if .gz file already read from disk
          file.zipBuffer = gzFile.buffer
        } else {
          file.zipBuffer = yield gzip(file.buffer)
        }
        this.set('Content-Encoding', 'gzip')
        this.body = file.zipBuffer
      } else {
        this.body = file.buffer
      }
      return
    }

    var stream = fs.createReadStream(file.path)

    // update file hash
    if (!file.md5) {
      var hash = crypto.createHash('md5')
      stream.on('data', hash.update.bind(hash))
      stream.on('end', function () {
        file.md5 = hash.digest('base64')
      })
    }

    this.body = stream
    // enable gzip will remove content length
    if (shouldGzip) {
      this.remove('Content-Length')
      this.set('Content-Encoding', 'gzip')
      this.body = stream.pipe(zlib.createGzip())
    }
  }
コード例 #10
0
ファイル: index.js プロジェクト: jimlambie/web
  this.server.app.use(function cache (req, res, next) {
    var enabled = self.cachingEnabled(req)

    if (!enabled) return next()

    debug('%s%s, cache enabled: %s', req.headers.host, req.url, enabled)

    // Check it's a page
    if (!self.getEndpoint(req)) return next()

    // get contentType that current endpoint requires
    var contentType = self.getReqContentType(req)

    // only cache GET requests
    if (req.method && req.method.toLowerCase() !== 'get') return next()

    // we build the filename with a hashed hex string so we can be unique
    // and avoid using file system reserved characters in the name
    var requestUrl = url.parse(req.url, true).path

    // get the host key that matches the request's host header
    const virtualHosts = config.get('virtualHosts')

    const host =
      Object.keys(virtualHosts).find(key => {
        return virtualHosts.hostnames.includes(req.headers.host)
      }) || ''

    var filename = crypto
      .createHash('sha1')
      .update(`${host}${requestUrl}`)
      .digest('hex')

    // allow query string param to bypass cache
    var query = url.parse(req.url, true).query
    var noCache =
      query.cache && query.cache.toString().toLowerCase() === 'false'

    // File extension for cache file
    var cacheExt =
      compressible(contentType) && help.canCompress(req.headers)
        ? '.' + help.canCompress(req.headers)
        : null

    var opts = {
      directory: { extension: mime.extension(contentType) + cacheExt }
    }

    // Compression settings
    var shouldCompress = compressible(contentType)
      ? help.canCompress(req.headers)
      : false

    // attempt to get from the cache
    self.cache
      .get(filename, opts)
      .then(stream => {
        debug('serving %s%s from cache', req.headers.host, req.url)

        if (noCache) {
          res.setHeader('X-Cache-Lookup', 'HIT')
          res.setHeader('X-Cache', 'MISS')
          return next()
        }

        var headers = {
          'X-Cache-Lookup': 'HIT',
          'X-Cache': 'HIT',
          'Content-Type': contentType,
          'Cache-Control':
            config.get('headers.cacheControl')[contentType] ||
            'public, max-age=86400'
        }

        // Add compression headers
        if (shouldCompress) headers['Content-Encoding'] = shouldCompress

        // Add extra headers
        stream.on('open', fd => {
          fs.fstat(fd, (_, stats) => {
            res.setHeader('Content-Length', stats.size)
            res.setHeader('ETag', etag(stats))
          })
        })

        res.statusCode = 200
        Object.keys(headers).map(i => res.setHeader(i, headers[i]))

        stream.pipe(res)
      })
      .catch(() => {
        // not found in cache
        res.setHeader('X-Cache', 'MISS')
        res.setHeader('X-Cache-Lookup', 'MISS')

        return cacheResponse()
      })

    /**
     * Writes the current response body to either the filesystem or a Redis server,
     * depending on the configuration settings
     */
    function cacheResponse () {
      // file is expired or does not exist, wrap res.end and res.write to save to cache
      var _end = res.end
      var _write = res.write

      var data = []

      res.write = function (chunk) {
        if (chunk) data.push(chunk)

        _write.apply(res, arguments)
      }

      res.end = function (chunk) {
        // respond before attempting to cache
        _end.apply(res, arguments)

        if (chunk && !data.length) data.push(chunk)

        // if response is not 200 don't cache
        if (res.statusCode !== 200) return

        // cache the content, with applicable file extension
        try {
          self.cache.set(filename, Buffer.concat(data), opts).then(() => {})
        } catch (e) {
          console.log('Could not cache content: ' + requestUrl)
        }
      }

      return next()
    }
  })
コード例 #11
0
ファイル: upload.js プロジェクト: dkrick/node-s3upload
  , maybeGzip = function (contentType, buffer, callback) {
      if (!contentType || !compressible(contentType))
        return callback(null)

      zlib.gzip(buffer, callback)
    }
コード例 #12
0
exports.filter = function(req, res){
  return compressible(res.getHeader('Content-Type'));
};
コード例 #13
0
ファイル: index.js プロジェクト: ReganHe/Node-KOA
  return function* staticCache(next) {
    var file = files[safeDecodeURIComponent(this.path)]
    if (!file)
      return yield* next

    switch (this.method) {
      case 'HEAD':
      case 'GET':
        this.status = 200

        if (enableGzip) this.vary('Accept-Encoding')

        if (!file.buffer) {
          var stats = yield stat(file.path)
          if (stats.mtime > new Date(file.mtime)) {
            file.mtime = stats.mtime.toUTCString()
            file.md5 = null
            file.length = stats.size
          }
        }

        this.response.lastModified = file.mtime
        if (file.md5) this.response.etag = file.md5

        if (this.fresh)
          return this.status = 304

        this.type = file.type
        this.length = file.zipBuffer ? file.zipBuffer.length : file.length
        this.set('Cache-Control', file.cacheControl || 'public, max-age=' + file.maxAge)
        if (file.md5) this.set('Content-MD5', file.md5)

        if (this.method === 'HEAD')
          return

        var acceptGzip = this.acceptsEncodings('gzip') === 'gzip';

        if (file.zipBuffer) {
          if (acceptGzip) {
            this.set('Content-Encoding', 'gzip')
            this.body = file.zipBuffer
          } else {
            this.body = file.buffer
          }
          return
        }

        var shouldGzip = enableGzip
          && file.length > 1024
          && acceptGzip
          && compressible(file.type)

        if (file.buffer) {
          if (shouldGzip) {
            file.zipBuffer = yield gzip(file.buffer)
            this.set('Content-Encoding', 'gzip')
            this.body = file.zipBuffer
          } else {
            this.body = file.buffer
          }
          return
        }

        var stream = fs.createReadStream(file.path)

        // update file hash
        if (!file.md5) {
          var hash = crypto.createHash('md5')
          stream.on('data', hash.update.bind(hash))
          stream.on('end', function () {
            file.md5 = hash.digest('base64')
          })
        }

        this.body = stream
        // enable gzip will remove content length
        if (shouldGzip) {
          this.remove('Content-Length')
          this.set('Content-Encoding', 'gzip')
          this.body = stream.pipe(zlib.createGzip())
        }
        return
      case 'OPTIONS':
        this.status = 204
        this.set('Allow', 'HEAD,GET,OPTIONS')
        return
      default:
        this.status = 405
        this.set('Allow', 'HEAD,GET,OPTIONS')
        return
    }
  }