Initial commit for OpenECOMP SDN-C OA&M
[sdnc/oam.git] / dgbuilder / dgeflows / node_modules / express / node_modules / serve-static / index.js
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
13 var escapeHtml = require('escape-html');
14 var merge = require('utils-merge');
15 var parseurl = require('parseurl');
16 var resolve = require('path').resolve;
17 var send = require('send');
18 var url = require('url');
19
20 /**
21  * @param {String} root
22  * @param {Object} options
23  * @return {Function}
24  * @api public
25  */
26
27 exports = 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.path = null
84         originalUrl.pathname = collapseLeadingSlashes(originalUrl.pathname + '/')
85
86         // reformat the URL
87         var target = url.format(originalUrl)
88
89         // send redirect response
90         res.statusCode = 303
91         res.setHeader('Content-Type', 'text/html; charset=utf-8')
92         res.setHeader('Location', target)
93         res.end('Redirecting to <a href="' + escapeHtml(target) + '">' + escapeHtml(target) + '</a>\n')
94       })
95     } else {
96       // forward to next middleware on directory
97       stream.on('directory', next)
98     }
99
100     // add headers listener
101     if (setHeaders) {
102       stream.on('headers', setHeaders)
103     }
104
105     // forward non-404 errors
106     stream.on('error', function error(err) {
107       next(err.status === 404 ? null : err)
108     })
109
110     // pipe
111     stream.pipe(res)
112   }
113 }
114
115 /**
116  * Expose mime module.
117  *
118  * If you wish to extend the mime table use this
119  * reference to the "mime" module in the npm registry.
120  */
121
122 exports.mime = send.mime
123
124 /**
125  * Collapse all leading slashes into a single slash
126  * @private
127  */
128 function collapseLeadingSlashes(str) {
129   for (var i = 0; i < str.length; i++) {
130     if (str[i] !== '/') {
131       break
132     }
133   }
134
135   return i > 1
136     ? '/' + str.substr(i)
137     : str
138 }