Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / 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-2015 Douglas Christopher Wilson
6  * MIT Licensed
7  */
8
9 'use strict'
10
11 /**
12  * Module dependencies.
13  * @private
14  */
15
16 var escapeHtml = require('escape-html')
17 var parseUrl = require('parseurl')
18 var resolve = require('path').resolve
19 var send = require('send')
20 var url = require('url')
21
22 /**
23  * Module exports.
24  * @public
25  */
26
27 module.exports = serveStatic
28 module.exports.mime = send.mime
29
30 /**
31  * @param {string} root
32  * @param {object} [options]
33  * @return {function}
34  * @public
35  */
36
37 function serveStatic (root, options) {
38   if (!root) {
39     throw new TypeError('root path required')
40   }
41
42   if (typeof root !== 'string') {
43     throw new TypeError('root path must be a string')
44   }
45
46   // copy options object
47   var opts = Object.create(options || null)
48
49   // fall-though
50   var fallthrough = opts.fallthrough !== false
51
52   // default redirect
53   var redirect = opts.redirect !== false
54
55   // headers listener
56   var setHeaders = opts.setHeaders
57
58   if (setHeaders && typeof setHeaders !== 'function') {
59     throw new TypeError('option setHeaders must be function')
60   }
61
62   // setup options for send
63   opts.maxage = opts.maxage || opts.maxAge || 0
64   opts.root = resolve(root)
65
66   // construct directory listener
67   var onDirectory = redirect
68     ? createRedirectDirectoryListener()
69     : createNotFoundDirectoryListener()
70
71   return function serveStatic (req, res, next) {
72     if (req.method !== 'GET' && req.method !== 'HEAD') {
73       if (fallthrough) {
74         return next()
75       }
76
77       // method not allowed
78       res.statusCode = 405
79       res.setHeader('Allow', 'GET, HEAD')
80       res.setHeader('Content-Length', '0')
81       res.end()
82       return
83     }
84
85     var forwardError = !fallthrough
86     var originalUrl = parseUrl.original(req)
87     var path = parseUrl(req).pathname
88
89     // make sure redirect occurs at mount
90     if (path === '/' && originalUrl.pathname.substr(-1) !== '/') {
91       path = ''
92     }
93
94     // create send stream
95     var stream = send(req, path, opts)
96
97     // add directory handler
98     stream.on('directory', onDirectory)
99
100     // add headers listener
101     if (setHeaders) {
102       stream.on('headers', setHeaders)
103     }
104
105     // add file listener for fallthrough
106     if (fallthrough) {
107       stream.on('file', function onFile () {
108         // once file is determined, always forward error
109         forwardError = true
110       })
111     }
112
113     // forward errors
114     stream.on('error', function error (err) {
115       if (forwardError || !(err.statusCode < 500)) {
116         next(err)
117         return
118       }
119
120       next()
121     })
122
123     // pipe
124     stream.pipe(res)
125   }
126 }
127
128 /**
129  * Collapse all leading slashes into a single slash
130  * @private
131  */
132 function collapseLeadingSlashes (str) {
133   for (var i = 0; i < str.length; i++) {
134     if (str[i] !== '/') {
135       break
136     }
137   }
138
139   return i > 1
140     ? '/' + str.substr(i)
141     : str
142 }
143
144 /**
145  * Create a directory listener that just 404s.
146  * @private
147  */
148
149 function createNotFoundDirectoryListener () {
150   return function notFound () {
151     this.error(404)
152   }
153 }
154
155 /**
156  * Create a directory listener that performs a redirect.
157  * @private
158  */
159
160 function createRedirectDirectoryListener () {
161   return function redirect () {
162     if (this.hasTrailingSlash()) {
163       this.error(404)
164       return
165     }
166
167     // get original URL
168     var originalUrl = parseUrl.original(this.req)
169
170     // append trailing slash
171     originalUrl.path = null
172     originalUrl.pathname = collapseLeadingSlashes(originalUrl.pathname + '/')
173
174     // reformat the URL
175     var loc = url.format(originalUrl)
176     var msg = 'Redirecting to <a href="' + escapeHtml(loc) + '">' + escapeHtml(loc) + '</a>\n'
177     var res = this.res
178
179     // send redirect response
180     res.statusCode = 303
181     res.setHeader('Content-Type', 'text/html; charset=UTF-8')
182     res.setHeader('Content-Length', Buffer.byteLength(msg))
183     res.setHeader('X-Content-Type-Options', 'nosniff')
184     res.setHeader('Location', loc)
185     res.end(msg)
186   }
187 }