<commit_before>
// Express - Static - Copyright <NAME> <<EMAIL>> (MIT Licensed)

var path = require('path'),
    posix = require('posix')
    
// --- InvalidPathError

InvalidPathError = ExpressError.extend({
  name: 'InvalidPathError',
  init: function(path) {
    this.message = "`" + path + "' is not a valid path"
  }
})  
  
// --- File

exports.File = Class({
  
  /**
   * Initialize with file _path_.
   *
   * @param  {string} path
   * @api public
   */
  
  init: function(path) {
    this.path = path
    if (path.indexOf('..') != -1) throw new InvalidPathError(path)
  },
  
  /**
   * Transfer static file to the given _request_.
   *
   *  - Ensures the file exists
   *  - Ensures the file is a regular file (not FIFO, Socket, etc)
   *  - Automatically assigns content type
   *
   * @param  {Request} request
   * @api public
   */
  
  send: function(request) {
    var file = this.path
    path.exists(file, function(exists){
      if (!exists) request.halt()
      posix.stat(file).addCallback(function(stats){
        if (!stats.isFile()) request.halt()
        posix.cat(file, 'binary').addCallback(function(content){
          request.contentType(file)
          request.halt(200, content, 'binary')
        })
      })
    })
  }
})<commit_msg>Static file caching. Closes #136<commit_after>
// Express - Static - Copyright <NAME> <<EMAIL>> (MIT Licensed)

var path = require('path'),
    posix = require('posix')
    
// --- InvalidPathError

InvalidPathError = ExpressError.extend({
  name: 'InvalidPathError',
  init: function(path) {
    this.message = "`" + path + "' is not a valid path"
  }
})  
  
// --- File

exports.File = Class({
  
  /**
   * Initialize with file _path_.
   *
   * @param  {string} path
   * @api public
   */
  
  init: function(path) {
    this.path = path
    if (path.indexOf('..') != -1) throw new InvalidPathError(path)
  },
  
  /**
   * Transfer static file to the given _request_.
   *
   *  - Ensures the file exists
   *  - Ensures the file is a regular file (not FIFO, Socket, etc)
   *  - Automatically assigns content type
   *
   * @param  {Request} request
   * @api public
   */
  
  send: function(request) {
    var cache, file = this.path
    if (cache = request.cache.get(file))
      request.contentType(cache.type),
      request.halt(200, cache.content)
    path.exists(file, function(exists){
      if (!exists) request.halt()
      posix.stat(file).addCallback(function(stats){
        if (!stats.isFile()) request.halt()
        posix.cat(file, 'binary').addCallback(function(content){
          request.contentType(file)
          request.cache.set(file, { type: file, content: content })
          request.halt(200, content, 'binary')
        })
      })
    })
  }
})
{'fraction_non_alphanumeric': 0.14976372228280624, 'fraction_numerical': 0.005089058524173028, 'mean_word_length': 2.4616352201257863, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, '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': '6235076', 'n_tokens_mistral': 905, 'n_tokens_neox': 883, 'n_words': 216}