<commit_before>
/*!
 * Connect - staticCache
 * Copyright(c) 2011 Sencha Inc.
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var http = require('http')
  , utils = require('../utils')
  , Cache = require('../cache')
  , url = require('url')
  , fs = require('fs');

/**
 * Enables a memory cache layer on top of
 * the `static()` middleware, serving popular
 * static files.
 *
 * By default a maximum of 128 objects are
 * held in cache, with a max of 256k each,
 * totalling ~32mb.
 *
 * A Least-Recently-Used (LRU) cache algo
 * is implemented through the `Cache` object,
 * simply rotating cache objects as they are
 * hit. This means that increasingly popular
 * objects maintain their positions while
 * others get shoved out of the stack and
 * garbage collected.
 *
 * Benchmarks:
 *
 *     static(): 2700 rps
 *     node-static: 5300 rps
 *     static() + staticCache(): 7500 rps
 *
 * Options:
 *
 *   - `maxObjects`  max cache objects [128]
 *   - `maxLength`  max cache object length 256kb
 *
 * @param {Type} name
 * @return {Type}
 * @api public
 */

module.exports = function staticCache(options){
  var options = options || {}
    , cache = new Cache(options.maxObjects || 128)
    , maxlen = options.maxLength || 1024 * 256;

  return function staticCache(req, res, next){
    var path = url.parse(req.url).pathname
      , hit = cache.get(path)
      , hitCC // origin cache-control
      , uaCC // user agent cache-control
      , header
      , age;

    // cache static
    req.on('static', function(stream){
      // ignore larger files
      var headers = res._headers
        , cc = utils.parseCacheControl(headers['cache-control'] || '')
        , contentLength = headers['content-length'];
      if (!contentLength || contentLength > maxlen) return;

      // Dont cache items we shouldn't be
      if (cc['no-cache'] || cc['no-store'] || cc['private'] || cc['must-revalidate']) {
        return;
      }

      // If already in cache then validate
      var hit = cache.get(path);
      if (hit){
        if(headers.etag != hit[0].etag) {
          cache.remove(path);
        } else {
          hit.createdAt = new Date();
          return;
        }
      }

      // validation notifiactions don't contain a steam
      if(stream === null) {
        return;
      }

      // add the cache object
      var arr = cache.add(path);
      arr.push(headers);

      // store the chunks
      stream.on('data', function(chunk){
        arr.push(chunk);
      });

      // flag it as complete
      stream.on('end', function(){
        arr.complete = true;
      });
    });

    // cache hit
    if (hit && hit.complete) {
      // TODO: finish meeee... throttling etc
      header = utils.merge({},hit[0]); // Don't want to taint
      header.Age = age = (new Date - hit.createdAt) / 1000 | 0;
      header.date = new Date().toUTCString();

      // Parse cache-controls
      hitCC = utils.parseCacheControl(header['cache-control'] || '');
      uaCC = utils.parseCacheControl(req.headers['cache-control'] || '')

      // Check if we must revalidate(bypass)
      if (hitCC['no-cache'] || uaCC['no-cache']){
        return next();
      }

      // Check freshness of entity
      if (isStale(hitCC,age) || isStale(uaCC,age)){
        return next();
      }

      // conditional GET support
      if (utils.conditionalGET(req)) {
        if (!utils.modified(req, res, header)) {
          header['content-length'] = 0;
          res.writeHead(304, header)
          return res.end();
        }
      }

      // HEAD support
      if ('HEAD' == req.method) {
        header['content-length'] = 0;
        res.writeHead(200, header);
        return res.end();
      }

      // respond with cache
      res.writeHead(200, header);

      // backpressure
      function write(i) {
        var buf = hit[i];
        if (!buf) return res.end();
        if (false === res.write(buf)) {<commit_msg>refactored pull-request<commit_after>
/*!
 * Connect - staticCache
 * Copyright(c) 2011 Sencha Inc.
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var http = require('http')
  , utils = require('../utils')
  , Cache = require('../cache')
  , url = require('url')
  , fs = require('fs');

/**
 * Enables a memory cache layer on top of
 * the `static()` middleware, serving popular
 * static files.
 *
 * By default a maximum of 128 objects are
 * held in cache, with a max of 256k each,
 * totalling ~32mb.
 *
 * A Least-Recently-Used (LRU) cache algo
 * is implemented through the `Cache` object,
 * simply rotating cache objects as they are
 * hit. This means that increasingly popular
 * objects maintain their positions while
 * others get shoved out of the stack and
 * garbage collected.
 *
 * Benchmarks:
 *
 *     static(): 2700 rps
 *     node-static: 5300 rps
 *     static() + staticCache(): 7500 rps
 *
 * Options:
 *
 *   - `maxObjects`  max cache objects [128]
 *   - `maxLength`  max cache object length 256kb
 *
 * @param {Type} name
 * @return {Type}
 * @api public
 */

module.exports = function staticCache(options){
  var options = options || {}
    , cache = new Cache(options.maxObjects || 128)
    , maxlen = options.maxLength || 1024 * 256;

  return function staticCache(req, res, next){
    var path = url.parse(req.url).pathname
      , hit = cache.get(path)
      , hitCC
      , uaCC
      , header
      , age;

    // cache static
    req.on('static', function(stream){
      var headers = res._headers
        , cc = utils.parseCacheControl(headers['cache-control'] || '')
        , contentLength = headers['content-length']
        , hit;

      // ignore larger files
      if (!contentLength || contentLength > maxlen) return;

      // done cache items we shouldn't be
      if (cc['no-cache']
        || cc['no-store']
        || cc['private']
        || cc['must-revalidate']) return;

      // iif already in cache then validate
      if (hit = cache.get(path)){
        if (headers.etag == hit[0].etag) {
          hit.createdAt = new Date;
          return;
        } else {
          cache.remove(path);
        }
      }

      // validation notifiactions don't contain a steam
      if (null == stream) return;

      // add the cache object
      var arr = cache.add(path);
      arr.push(headers);

      // store the chunks
      stream.on('data', function(chunk){
        arr.push(chunk);
      });

      // flag it as complete
      stream.on('end', function(){
        arr.complete = true;
      });
    });

    // cache hit
    if (hit && hit.complete) {
      // TODO: finish meeee... throttling etc
      header = utils.merge({}, hit[0]);
      header.Age = age = (new Date - hit.createdAt) / 1000 | 0;
      header.date = new Date().toUTCString();

      // parse cache-controls
      hitCC = utils.parseCacheControl(header['cache-control'] || '');
      uaCC = utils.parseCacheControl(req.headers['cache-control'] || '')

      // check if we must revalidate(bypass)
      if (hitCC['no-cache'] || uaCC['no-cache']) return next();

      // check freshness of entity
      if (isStale(hitCC, age) || isStale(uaCC, age)) return next();

      // conditional GET support
      if (utils.conditionalGET(req)) {
        if (!utils.modified(req, res, header)) {
          header['content-length'] = 0;
          res.writeHead(304, header)
          return res.end();
        }
      }

      // HEAD support
      if ('HEAD' == req.method) {
        header['content-length'] = 0;
        res.writeHead(200, header);
        return res.end();
      }

      // respond with cache
      res.writeHead(200, header);

      // backpressure
      function write(i) {
        var buf = hit[i];
        if (!buf) return res.end();
        if (false === res.write(buf)) {
{'fraction_non_alphanumeric': 0.14387096774193547, 'fraction_numerical': 0.01496774193548387, 'mean_word_length': 2.1857788738183315, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1855305', 'n_tokens_mistral': 2443, 'n_tokens_neox': 2292, 'n_words': 664}