opusdev/vector-similarity-api
1
1/*!2 * serve-static3 * Copyright(c) 2010 Sencha Inc.4 * Copyright(c) 2011 TJ Holowaychuk5 * Copyright(c) 2014-2016 Douglas Christopher Wilson6 * MIT Licensed7 */8 9'use strict'10 11/**12 * Module dependencies.13 * @private14 */15 16var encodeUrl = require('encodeurl')17var escapeHtml = require('escape-html')18var parseUrl = require('parseurl')19var resolve = require('path').resolve20var send = require('send')21var url = require('url')22 23/**24 * Module exports.25 * @public26 */27 28module.exports = serveStatic29module.exports.mime = send.mime30 31/**32 * @param {string} root33 * @param {object} [options]34 * @return {function}35 * @public36 */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 object48 var opts = Object.create(options || null)49 50 // fall-though51 var fallthrough = opts.fallthrough !== false52 53 // default redirect54 var redirect = opts.redirect !== false55 56 // headers listener57 var setHeaders = opts.setHeaders58 59 if (setHeaders && typeof setHeaders !== 'function') {60 throw new TypeError('option setHeaders must be function')61 }62 63 // setup options for send64 opts.maxage = opts.maxage || opts.maxAge || 065 opts.root = resolve(root)66 67 // construct directory listener68 var onDirectory = redirect69 ? 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 allowed79 res.statusCode = 40580 res.setHeader('Allow', 'GET, HEAD')81 res.setHeader('Content-Length', '0')82 res.end()83 return84 }85 86 var forwardError = !fallthrough87 var originalUrl = parseUrl.original(req)88 var path = parseUrl(req).pathname89 90 // make sure redirect occurs at mount91 if (path === '/' && originalUrl.pathname.substr(-1) !== '/') {92 path = ''93 }94 95 // create send stream96 var stream = send(req, path, opts)97 98 // add directory handler99 stream.on('directory', onDirectory)100 101 // add headers listener102 if (setHeaders) {103 stream.on('headers', setHeaders)104 }105 106 // add file listener for fallthrough107 if (fallthrough) {108 stream.on('file', function onFile () {109 // once file is determined, always forward error110 forwardError = true111 })112 }113 114 // forward errors115 stream.on('error', function error (err) {116 if (forwardError || !(err.statusCode < 500)) {117 next(err)118 return119 }120 121 next()122 })123 124 // pipe125 stream.pipe(res)126 }127}128 129/**130 * Collapse all leading slashes into a single slash131 * @private132 */133function collapseLeadingSlashes (str) {134 for (var i = 0; i < str.length; i++) {135 if (str.charCodeAt(i) !== 0x2f /* / */) {136 break137 }138 }139 140 return i > 1141 ? '/' + str.substr(i)142 : str143}144 145/**146 * Create a minimal HTML document.147 *148 * @param {string} title149 * @param {string} body150 * @private151 */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 * @private169 */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 * @private180 */181 182function createRedirectDirectoryListener () {183 return function redirect (res) {184 if (this.hasTrailingSlash()) {185 this.error(404)186 return187 }188 189 // get original URL190 var originalUrl = parseUrl.original(this.req)191 192 // append trailing slash193 originalUrl.path = null194 originalUrl.pathname = collapseLeadingSlashes(originalUrl.pathname + '/')195 196 // reformat the URL197 var loc = encodeUrl(url.format(originalUrl))198 var doc = createHtmlDocument('Redirecting', 'Redirecting to ' + escapeHtml(loc))199 200 // send redirect response201 res.statusCode = 301202 res.setHeader('Content-Type', 'text/html; charset=UTF-8')203 res.setHeader('Content-Length', Buffer.byteLength(doc))204 res.setHeader('Content-Security-Policy', "default-src 'none'")205 res.setHeader('X-Content-Type-Options', 'nosniff')206 res.setHeader('Location', loc)207 res.end(doc)208 }209}210 