/* automatically generated by JSCoverage - do not edit */
if (typeof _$jscoverage === 'undefined') _$jscoverage = {};
if (! _$jscoverage['middleware/staticCache.js']) {
  _$jscoverage['middleware/staticCache.js'] = [];
  _$jscoverage['middleware/staticCache.js'][12] = 0;
  _$jscoverage['middleware/staticCache.js'][51] = 0;
  _$jscoverage['middleware/staticCache.js'][52] = 0;
  _$jscoverage['middleware/staticCache.js'][56] = 0;
  _$jscoverage['middleware/staticCache.js'][57] = 0;
  _$jscoverage['middleware/staticCache.js'][59] = 0;
  _$jscoverage['middleware/staticCache.js'][60] = 0;
  _$jscoverage['middleware/staticCache.js'][68] = 0;
  _$jscoverage['middleware/staticCache.js'][69] = 0;
  _$jscoverage['middleware/staticCache.js'][75] = 0;
  _$jscoverage['middleware/staticCache.js'][78] = 0;
  _$jscoverage['middleware/staticCache.js'][81] = 0;
  _$jscoverage['middleware/staticCache.js'][84] = 0;
  _$jscoverage['middleware/staticCache.js'][88] = 0;
  _$jscoverage['middleware/staticCache.js'][91] = 0;
  _$jscoverage['middleware/staticCache.js'][94] = 0;
  _$jscoverage['middleware/staticCache.js'][95] = 0;
  _$jscoverage['middleware/staticCache.js'][96] = 0;
  _$jscoverage['middleware/staticCache.js'][97] = 0;
  _$jscoverage['middleware/staticCache.js'][99] = 0;
  _$jscoverage['middleware/staticCache.js'][104] = 0;
  _$jscoverage['middleware/staticCache.js'][107] = 0;
  _$jscoverage['middleware/staticCache.js'][110] = 0;
  _$jscoverage['middleware/staticCache.js'][111] = 0;
  _$jscoverage['middleware/staticCache.js'][115] = 0;
  _$jscoverage['middleware/staticCache.js'][116] = 0;
  _$jscoverage['middleware/staticCache.js'][117] = 0;
  _$jscoverage['middleware/staticCache.js'][118] = 0;
  _$jscoverage['middleware/staticCache.js'][119] = 0;
  _$jscoverage['middleware/staticCache.js'][120] = 0;
  _$jscoverage['middleware/staticCache.js'][124] = 0;
  _$jscoverage['middleware/staticCache.js'][125] = 0;
  _$jscoverage['middleware/staticCache.js'][126] = 0;
  _$jscoverage['middleware/staticCache.js'][127] = 0;
  _$jscoverage['middleware/staticCache.js'][128] = 0;
  _$jscoverage['middleware/staticCache.js'][129] = 0;
  _$jscoverage['middleware/staticCache.js'][131] = 0;
  _$jscoverage['middleware/staticCache.js'][132] = 0;
  _$jscoverage['middleware/staticCache.js'][135] = 0;
  _$jscoverage['middleware/staticCache.js'][151] = 0;
  _$jscoverage['middleware/staticCache.js'][152] = 0;
  _$jscoverage['middleware/staticCache.js'][156] = 0;
  _$jscoverage['middleware/staticCache.js'][158] = 0;
  _$jscoverage['middleware/staticCache.js'][160] = 0;
  _$jscoverage['middleware/staticCache.js'][161] = 0;
  _$jscoverage['middleware/staticCache.js'][162] = 0;
  _$jscoverage['middleware/staticCache.js'][164] = 0;
  _$jscoverage['middleware/staticCache.js'][165] = 0;
  _$jscoverage['middleware/staticCache.js'][166] = 0;
  _$jscoverage['middleware/staticCache.js'][167] = 0;
  _$jscoverage['middleware/staticCache.js'][169] = 0;
  _$jscoverage['middleware/staticCache.js'][171] = 0;
  _$jscoverage['middleware/staticCache.js'][172] = 0;
  _$jscoverage['middleware/staticCache.js'][173] = 0;
  _$jscoverage['middleware/staticCache.js'][174] = 0;
  _$jscoverage['middleware/staticCache.js'][175] = 0;
  _$jscoverage['middleware/staticCache.js'][178] = 0;
  _$jscoverage['middleware/staticCache.js'][181] = 0;
  _$jscoverage['middleware/staticCache.js'][183] = 0;
  _$jscoverage['middleware/staticCache.js'][186] = 0;
  _$jscoverage['middleware/staticCache.js'][187] = 0;
  _$jscoverage['middleware/staticCache.js'][200] = 0;
  _$jscoverage['middleware/staticCache.js'][201] = 0;
  _$jscoverage['middleware/staticCache.js'][206] = 0;
  _$jscoverage['middleware/staticCache.js'][208] = 0;
  _$jscoverage['middleware/staticCache.js'][210] = 0;
  _$jscoverage['middleware/staticCache.js'][212] = 0;
  _$jscoverage['middleware/staticCache.js'][214] = 0;
  _$jscoverage['middleware/staticCache.js'][216] = 0;
  _$jscoverage['middleware/staticCache.js'][229] = 0;
  _$jscoverage['middleware/staticCache.js'][230] = 0;
}
_$jscoverage['middleware/staticCache.js'][12]++;
var utils = require("../utils"), Cache = require("../cache"), fresh = require("fresh");
_$jscoverage['middleware/staticCache.js'][51]++;
module.exports = (function staticCache(options) {
  _$jscoverage['middleware/staticCache.js'][52]++;
  var options = options || {}, cache = new Cache(options.maxObjects || 128), maxlen = options.maxLength || 262144;
  _$jscoverage['middleware/staticCache.js'][56]++;
  console.warn("connect.staticCache() is deprecated and will be removed in 3.0");
  _$jscoverage['middleware/staticCache.js'][57]++;
  console.warn("use varnish or similar reverse proxy caches.");
  _$jscoverage['middleware/staticCache.js'][59]++;
  return (function staticCache(req, res, next) {
  _$jscoverage['middleware/staticCache.js'][60]++;
  var key = cacheKey(req), ranges = req.headers.range, hasCookies = req.headers.cookie, hit = cache.get(key);
  _$jscoverage['middleware/staticCache.js'][68]++;
  req.on("static", (function (stream) {
  _$jscoverage['middleware/staticCache.js'][69]++;
  var headers = res._headers, cc = utils.parseCacheControl(headers["cache-control"] || ""), contentLength = headers["content-length"], hit;
  _$jscoverage['middleware/staticCache.js'][75]++;
  if (headers["set-cookie"]) {
    _$jscoverage['middleware/staticCache.js'][75]++;
    return hasCookies = true;
  }
  _$jscoverage['middleware/staticCache.js'][78]++;
  if (hasCookies) {
    _$jscoverage['middleware/staticCache.js'][78]++;
    return;
  }
  _$jscoverage['middleware/staticCache.js'][81]++;
  if (! contentLength || contentLength > maxlen) {
    _$jscoverage['middleware/staticCache.js'][81]++;
    return;
  }
  _$jscoverage['middleware/staticCache.js'][84]++;
  if (headers["content-range"]) {
    _$jscoverage['middleware/staticCache.js'][84]++;
    return;
  }
  _$jscoverage['middleware/staticCache.js'][88]++;
  if (cc["no-cache"] || cc["no-store"] || cc["private"] || cc["must-revalidate"]) {
    _$jscoverage['middleware/staticCache.js'][91]++;
    return;
  }
  _$jscoverage['middleware/staticCache.js'][94]++;
  if (hit = cache.get(key)) {
    _$jscoverage['middleware/staticCache.js'][95]++;
    if (headers.etag == hit[0].etag) {
      _$jscoverage['middleware/staticCache.js'][96]++;
      hit[0].date = new Date();
      _$jscoverage['middleware/staticCache.js'][97]++;
      return;
    }
    else {
      _$jscoverage['middleware/staticCache.js'][99]++;
      cache.remove(key);
    }
  }
  _$jscoverage['middleware/staticCache.js'][104]++;
  if (null == stream) {
    _$jscoverage['middleware/staticCache.js'][104]++;
    return;
  }
  _$jscoverage['middleware/staticCache.js'][107]++;
  var arr = [];
  _$jscoverage['middleware/staticCache.js'][110]++;
  stream.on("data", (function (chunk) {
  _$jscoverage['middleware/staticCache.js'][111]++;
  arr.push(chunk);
}));
  _$jscoverage['middleware/staticCache.js'][115]++;
  stream.on("end", (function () {
  _$jscoverage['middleware/staticCache.js'][116]++;
  var cacheEntry = cache.add(key);
  _$jscoverage['middleware/staticCache.js'][117]++;
  delete headers["x-cache"];
  _$jscoverage['middleware/staticCache.js'][118]++;
  cacheEntry.push(200);
  _$jscoverage['middleware/staticCache.js'][119]++;
  cacheEntry.push(headers);
  _$jscoverage['middleware/staticCache.js'][120]++;
  cacheEntry.push.apply(cacheEntry, arr);
}));
}));
  _$jscoverage['middleware/staticCache.js'][124]++;
  if (req.method == "GET" || req.method == "HEAD") {
    _$jscoverage['middleware/staticCache.js'][125]++;
    if (ranges) {
      _$jscoverage['middleware/staticCache.js'][126]++;
      next();
    }
    else {
      _$jscoverage['middleware/staticCache.js'][127]++;
      if (! hasCookies && hit && ! mustRevalidate(req, hit)) {
        _$jscoverage['middleware/staticCache.js'][128]++;
        res.setHeader("X-Cache", "HIT");
        _$jscoverage['middleware/staticCache.js'][129]++;
        respondFromCache(req, res, hit);
      }
      else {
        _$jscoverage['middleware/staticCache.js'][131]++;
        res.setHeader("X-Cache", "MISS");
        _$jscoverage['middleware/staticCache.js'][132]++;
        next();
      }
    }
  }
  else {
    _$jscoverage['middleware/staticCache.js'][135]++;
    next();
  }
});
});
_$jscoverage['middleware/staticCache.js'][151]++;
function respondFromCache(req, res, cacheEntry) {
  _$jscoverage['middleware/staticCache.js'][152]++;
  var status = cacheEntry[0], headers = utils.merge({}, cacheEntry[1]), content = cacheEntry.slice(2);
  _$jscoverage['middleware/staticCache.js'][156]++;
  headers.age = (new Date() - new Date(headers.date)) / 1000 || 0;
  _$jscoverage['middleware/staticCache.js'][158]++;
  switch (req.method) {
  case "HEAD":
    _$jscoverage['middleware/staticCache.js'][160]++;
    res.writeHead(status, headers);
    _$jscoverage['middleware/staticCache.js'][161]++;
    res.end();
    _$jscoverage['middleware/staticCache.js'][162]++;
    break;
  case "GET":
    _$jscoverage['middleware/staticCache.js'][164]++;
    if (utils.conditionalGET(req) && fresh(req.headers, headers)) {
      _$jscoverage['middleware/staticCache.js'][165]++;
      headers["content-length"] = 0;
      _$jscoverage['middleware/staticCache.js'][166]++;
      res.writeHead(304, headers);
      _$jscoverage['middleware/staticCache.js'][167]++;
      res.end();
    }
    else {
      _$jscoverage['middleware/staticCache.js'][169]++;
      res.writeHead(status, headers);
      _$jscoverage['middleware/staticCache.js'][171]++;
      function write() {
        _$jscoverage['middleware/staticCache.js'][172]++;
        while (content.length) {
          _$jscoverage['middleware/staticCache.js'][173]++;
          if (false === res.write(content.shift())) {
            _$jscoverage['middleware/staticCache.js'][174]++;
            res.once("drain", write);
            _$jscoverage['middleware/staticCache.js'][175]++;
            return;
          }
}
        _$jscoverage['middleware/staticCache.js'][178]++;
        res.end();
}
      _$jscoverage['middleware/staticCache.js'][181]++;
      write();
    }
    _$jscoverage['middleware/staticCache.js'][183]++;
    break;
  default:
    _$jscoverage['middleware/staticCache.js'][186]++;
    res.writeHead(500, "");
    _$jscoverage['middleware/staticCache.js'][187]++;
    res.end();
  }
}
_$jscoverage['middleware/staticCache.js'][200]++;
function mustRevalidate(req, cacheEntry) {
  _$jscoverage['middleware/staticCache.js'][201]++;
  var cacheHeaders = cacheEntry[1], reqCC = utils.parseCacheControl(req.headers["cache-control"] || ""), cacheCC = utils.parseCacheControl(cacheHeaders["cache-control"] || ""), cacheAge = (new Date() - new Date(cacheHeaders.date)) / 1000 || 0;
  _$jscoverage['middleware/staticCache.js'][206]++;
  if (cacheCC["no-cache"] || cacheCC["must-revalidate"] || cacheCC["proxy-revalidate"]) {
    _$jscoverage['middleware/staticCache.js'][208]++;
    return true;
  }
  _$jscoverage['middleware/staticCache.js'][210]++;
  if (reqCC["no-cache"]) {
    _$jscoverage['middleware/staticCache.js'][210]++;
    return true;
  }
  _$jscoverage['middleware/staticCache.js'][212]++;
  if (null != reqCC["max-age"]) {
    _$jscoverage['middleware/staticCache.js'][212]++;
    return reqCC["max-age"] < cacheAge;
  }
  _$jscoverage['middleware/staticCache.js'][214]++;
  if (null != cacheCC["max-age"]) {
    _$jscoverage['middleware/staticCache.js'][214]++;
    return cacheCC["max-age"] < cacheAge;
  }
  _$jscoverage['middleware/staticCache.js'][216]++;
  return false;
}
_$jscoverage['middleware/staticCache.js'][229]++;
function cacheKey(req) {
  _$jscoverage['middleware/staticCache.js'][230]++;
  return utils.parseUrl(req).path;
}
_$jscoverage['middleware/staticCache.js'].source = ["","/*!"," * Connect - staticCache"," * Copyright(c) 2011 Sencha Inc."," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var utils = require('../utils')","  , Cache = require('../cache')","  , fresh = require('fresh');","","/**"," * Static cache:"," *"," * 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 {Object} options"," * @return {Function}"," * @api public"," */","","module.exports = function staticCache(options){","  var options = options || {}","    , cache = new Cache(options.maxObjects || 128)","    , maxlen = options.maxLength || 1024 * 256;","","  console.warn('connect.staticCache() is deprecated and will be removed in 3.0');","  console.warn('use varnish or similar reverse proxy caches.');","","  return function staticCache(req, res, next){","    var key = cacheKey(req)","      , ranges = req.headers.range","      , hasCookies = req.headers.cookie","      , hit = cache.get(key);","","    // cache static","    // TODO: change from staticCache() -&gt; cache()","    // and make this work for any request","    req.on('static', function(stream){","      var headers = res._headers","        , cc = utils.parseCacheControl(headers['cache-control'] || '')","        , contentLength = headers['content-length']","        , hit;","","      // dont cache set-cookie responses","      if (headers['set-cookie']) return hasCookies = true;","","      // dont cache when cookies are present","      if (hasCookies) return;","","      // ignore larger files","      if (!contentLength || contentLength &gt; maxlen) return;","","      // don't cache partial files","      if (headers['content-range']) return;","","      // dont cache items we shouldn't be","      // TODO: real support for must-revalidate / no-cache","      if ( cc['no-cache']","        || cc['no-store']","        || cc['private']","        || cc['must-revalidate']) return;","","      // if already in cache then validate","      if (hit = cache.get(key)){","        if (headers.etag == hit[0].etag) {","          hit[0].date = new Date;","          return;","        } else {","          cache.remove(key);","        }","      }","","      // validation notifiactions don't contain a steam","      if (null == stream) return;","","      // add the cache object","      var arr = [];","","      // store the chunks","      stream.on('data', function(chunk){","        arr.push(chunk);","      });","","      // flag it as complete","      stream.on('end', function(){","        var cacheEntry = cache.add(key);","        delete headers['x-cache']; // Clean up (TODO: others)","        cacheEntry.push(200);","        cacheEntry.push(headers);","        cacheEntry.push.apply(cacheEntry, arr);","      });","    });","","    if (req.method == 'GET' || req.method == 'HEAD') {","      if (ranges) {","        next();","      } else if (!hasCookies &amp;&amp; hit &amp;&amp; !mustRevalidate(req, hit)) {","        res.setHeader('X-Cache', 'HIT');","        respondFromCache(req, res, hit);","      } else {","        res.setHeader('X-Cache', 'MISS');","        next();","      }","    } else {","      next();","    }","  }","};","","/**"," * Respond with the provided cached value."," * TODO: Assume 200 code, that's iffy."," *"," * @param {Object} req"," * @param {Object} res"," * @param {Object} cacheEntry"," * @return {String}"," * @api private"," */","","function respondFromCache(req, res, cacheEntry) {","  var status = cacheEntry[0]","    , headers = utils.merge({}, cacheEntry[1])","    , content = cacheEntry.slice(2);","","  headers.age = (new Date - new Date(headers.date)) / 1000 || 0;","","  switch (req.method) {","    case 'HEAD':","      res.writeHead(status, headers);","      res.end();","      break;","    case 'GET':","      if (utils.conditionalGET(req) &amp;&amp; fresh(req.headers, headers)) {","        headers['content-length'] = 0;","        res.writeHead(304, headers);","        res.end();","      } else {","        res.writeHead(status, headers);","","        function write() {","          while (content.length) {","            if (false === res.write(content.shift())) {","              res.once('drain', write);","              return;","            }","          }","          res.end();","        }","","        write();","      }","      break;","    default:","      // This should never happen.","      res.writeHead(500, '');","      res.end();","  }","}","","/**"," * Determine whether or not a cached value must be revalidated."," *"," * @param {Object} req"," * @param {Object} cacheEntry"," * @return {String}"," * @api private"," */","","function mustRevalidate(req, cacheEntry) {","  var cacheHeaders = cacheEntry[1]","    , reqCC = utils.parseCacheControl(req.headers['cache-control'] || '')","    , cacheCC = utils.parseCacheControl(cacheHeaders['cache-control'] || '')","    , cacheAge = (new Date - new Date(cacheHeaders.date)) / 1000 || 0;","","  if ( cacheCC['no-cache']","    || cacheCC['must-revalidate']","    || cacheCC['proxy-revalidate']) return true;","","  if (reqCC['no-cache']) return true;","","  if (null != reqCC['max-age']) return reqCC['max-age'] &lt; cacheAge;","","  if (null != cacheCC['max-age']) return cacheCC['max-age'] &lt; cacheAge;","","  return false;","}","","/**"," * The key to use in the cache. For now, this is the URL path and query."," *"," * 'http://example.com?key=value' -&gt; '/?key=value'"," *"," * @param {Object} req"," * @return {String}"," * @api private"," */","","function cacheKey(req) {","  return utils.parseUrl(req).path;","}"];
