source: trip-planner-front/node_modules/serve-static/index.js@ 8d391a1

Last change on this file since 8d391a1 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 4.5 KB
Line 
1/*!
2 * serve-static
3 * Copyright(c) 2010 Sencha Inc.
4 * Copyright(c) 2011 TJ Holowaychuk
5 * Copyright(c) 2014-2016 Douglas Christopher Wilson
6 * MIT Licensed
7 */
8
9'use strict'
10
11/**
12 * Module dependencies.
13 * @private
14 */
15
16var encodeUrl = require('encodeurl')
17var escapeHtml = require('escape-html')
18var parseUrl = require('parseurl')
19var resolve = require('path').resolve
20var send = require('send')
21var url = require('url')
22
23/**
24 * Module exports.
25 * @public
26 */
27
28module.exports = serveStatic
29module.exports.mime = send.mime
30
31/**
32 * @param {string} root
33 * @param {object} [options]
34 * @return {function}
35 * @public
36 */
37
38function serveStatic (root, options) {
39 if (!root) {
40 throw new TypeError('root path required')
41 }
42
43 if (typeof root !== 'string') {
44 throw new TypeError('root path must be a string')
45 }
46
47 // copy options object
48 var opts = Object.create(options || null)
49
50 // fall-though
51 var fallthrough = opts.fallthrough !== false
52
53 // default redirect
54 var redirect = opts.redirect !== false
55
56 // headers listener
57 var setHeaders = opts.setHeaders
58
59 if (setHeaders && typeof setHeaders !== 'function') {
60 throw new TypeError('option setHeaders must be function')
61 }
62
63 // setup options for send
64 opts.maxage = opts.maxage || opts.maxAge || 0
65 opts.root = resolve(root)
66
67 // construct directory listener
68 var onDirectory = redirect
69 ? createRedirectDirectoryListener()
70 : createNotFoundDirectoryListener()
71
72 return function serveStatic (req, res, next) {
73 if (req.method !== 'GET' && req.method !== 'HEAD') {
74 if (fallthrough) {
75 return next()
76 }
77
78 // method not allowed
79 res.statusCode = 405
80 res.setHeader('Allow', 'GET, HEAD')
81 res.setHeader('Content-Length', '0')
82 res.end()
83 return
84 }
85
86 var forwardError = !fallthrough
87 var originalUrl = parseUrl.original(req)
88 var path = parseUrl(req).pathname
89
90 // make sure redirect occurs at mount
91 if (path === '/' && originalUrl.pathname.substr(-1) !== '/') {
92 path = ''
93 }
94
95 // create send stream
96 var stream = send(req, path, opts)
97
98 // add directory handler
99 stream.on('directory', onDirectory)
100
101 // add headers listener
102 if (setHeaders) {
103 stream.on('headers', setHeaders)
104 }
105
106 // add file listener for fallthrough
107 if (fallthrough) {
108 stream.on('file', function onFile () {
109 // once file is determined, always forward error
110 forwardError = true
111 })
112 }
113
114 // forward errors
115 stream.on('error', function error (err) {
116 if (forwardError || !(err.statusCode < 500)) {
117 next(err)
118 return
119 }
120
121 next()
122 })
123
124 // pipe
125 stream.pipe(res)
126 }
127}
128
129/**
130 * Collapse all leading slashes into a single slash
131 * @private
132 */
133function collapseLeadingSlashes (str) {
134 for (var i = 0; i < str.length; i++) {
135 if (str.charCodeAt(i) !== 0x2f /* / */) {
136 break
137 }
138 }
139
140 return i > 1
141 ? '/' + str.substr(i)
142 : str
143}
144
145/**
146 * Create a minimal HTML document.
147 *
148 * @param {string} title
149 * @param {string} body
150 * @private
151 */
152
153function createHtmlDocument (title, body) {
154 return '<!DOCTYPE html>\n' +
155 '<html lang="en">\n' +
156 '<head>\n' +
157 '<meta charset="utf-8">\n' +
158 '<title>' + title + '</title>\n' +
159 '</head>\n' +
160 '<body>\n' +
161 '<pre>' + body + '</pre>\n' +
162 '</body>\n' +
163 '</html>\n'
164}
165
166/**
167 * Create a directory listener that just 404s.
168 * @private
169 */
170
171function createNotFoundDirectoryListener () {
172 return function notFound () {
173 this.error(404)
174 }
175}
176
177/**
178 * Create a directory listener that performs a redirect.
179 * @private
180 */
181
182function createRedirectDirectoryListener () {
183 return function redirect (res) {
184 if (this.hasTrailingSlash()) {
185 this.error(404)
186 return
187 }
188
189 // get original URL
190 var originalUrl = parseUrl.original(this.req)
191
192 // append trailing slash
193 originalUrl.path = null
194 originalUrl.pathname = collapseLeadingSlashes(originalUrl.pathname + '/')
195
196 // reformat the URL
197 var loc = encodeUrl(url.format(originalUrl))
198 var doc = createHtmlDocument('Redirecting', 'Redirecting to <a href="' + escapeHtml(loc) + '">' +
199 escapeHtml(loc) + '</a>')
200
201 // send redirect response
202 res.statusCode = 301
203 res.setHeader('Content-Type', 'text/html; charset=UTF-8')
204 res.setHeader('Content-Length', Buffer.byteLength(doc))
205 res.setHeader('Content-Security-Policy', "default-src 'none'")
206 res.setHeader('X-Content-Type-Options', 'nosniff')
207 res.setHeader('Location', loc)
208 res.end(doc)
209 }
210}
Note: See TracBrowser for help on using the repository browser.