arnaucube
arnaucube/socketioMEANseedPublic Self-hosted repository
socketioMEANseed/server/node_modules/serve-static/index.js
server/node_modules/serve-static/index.jsRaw
  1/*!
  2 * serve-static
  3 * Copyright(c) 2010 Sencha Inc.
  4 * Copyright(c) 2011 TJ Holowaychuk
  5 * Copyright(c) 2014 Douglas Christopher Wilson
  6 * MIT Licensed
  7 */
  8
  9/**
 10 * Module dependencies.
 11 */
 12
 13var escapeHtml = require('escape-html');
 14var merge = require('utils-merge');
 15var parseurl = require('parseurl');
 16var resolve = require('path').resolve;
 17var send = require('send');
 18var url = require('url');
 19
 20/**
 21 * @param {String} root
 22 * @param {Object} options
 23 * @return {Function}
 24 * @api public
 25 */
 26
 27exports = module.exports = function serveStatic(root, options) {
 28  if (!root) {
 29    throw new TypeError('root path required')
 30  }
 31
 32  if (typeof root !== 'string') {
 33    throw new TypeError('root path must be a string')
 34  }
 35
 36  // copy options object
 37  options = merge({}, options)
 38
 39  // resolve root to absolute
 40  root = resolve(root)
 41
 42  // default redirect
 43  var redirect = options.redirect !== false
 44
 45  // headers listener
 46  var setHeaders = options.setHeaders
 47  delete options.setHeaders
 48
 49  if (setHeaders && typeof setHeaders !== 'function') {
 50    throw new TypeError('option setHeaders must be function')
 51  }
 52
 53  // setup options for send
 54  options.maxage = options.maxage || options.maxAge || 0
 55  options.root = root
 56
 57  return function serveStatic(req, res, next) {
 58    if (req.method !== 'GET' && req.method !== 'HEAD') {
 59      return next()
 60    }
 61
 62    var opts = merge({}, options)
 63    var originalUrl = parseurl.original(req)
 64    var path = parseurl(req).pathname
 65    var hasTrailingSlash = originalUrl.pathname[originalUrl.pathname.length - 1] === '/'
 66
 67    if (path === '/' && !hasTrailingSlash) {
 68      // make sure redirect occurs at mount
 69      path = ''
 70    }
 71
 72    // create send stream
 73    var stream = send(req, path, opts)
 74
 75    if (redirect) {
 76      // redirect relative to originalUrl
 77      stream.on('directory', function redirect() {
 78        if (hasTrailingSlash) {
 79          return next()
 80        }
 81
 82        // append trailing slash
 83        originalUrl.pathname = collapseLeadingSlashes(originalUrl.pathname + '/')
 84
 85        // reformat the URL
 86        var target = url.format(originalUrl)
 87
 88        // send redirect response
 89        res.statusCode = 303
 90        res.setHeader('Content-Type', 'text/html; charset=utf-8')
 91        res.setHeader('Location', target)
 92        res.end('Redirecting to <a href="' + escapeHtml(target) + '">' + escapeHtml(target) + '</a>\n')
 93      })
 94    } else {
 95      // forward to next middleware on directory
 96      stream.on('directory', next)
 97    }
 98
 99    // add headers listener
100    if (setHeaders) {
101      stream.on('headers', setHeaders)
102    }
103
104    // forward non-404 errors
105    stream.on('error', function error(err) {
106      next(err.status === 404 ? null : err)
107    })
108
109    // pipe
110    stream.pipe(res)
111  }
112}
113
114/**
115 * Expose mime module.
116 *
117 * If you wish to extend the mime table use this
118 * reference to the "mime" module in the npm registry.
119 */
120
121exports.mime = send.mime
122
123/**
124 * Collapse all leading slashes into a single slash
125 * @private
126 */
127function collapseLeadingSlashes(str) {
128  for (var i = 0; i < str.length; i++) {
129    if (str[i] !== '/') {
130      break
131    }
132  }
133
134  return i > 1
135    ? '/' + str.substr(i)
136    : str
137}