-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathindex.js
113 lines (90 loc) · 3.1 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
'use strict'
/**
* Module dependencies
*/
const assert = require('assert')
const send = require('koa-send')
const normalize = require('upath').normalizeSafe
const resolve = require('path').resolve
const fs = require('fs').promises
module.exports = serve
/**
* Serve static files from `rootDir`.
*
* Serves files from specified directory at specified path or from root.
* Supports 'index' file.
*
* @param {Object} options
* @return {Object} - {Function} serve
* @api public
*/
function serve(opts) {
assert(typeof opts.rootDir === 'string', 'rootDir must be specified (as a string)')
let options = opts || {}
options.root = resolve(options.rootDir || process.cwd())
// due to backward compatibility uses "index.html" as default but also supports disabling that with ""
options.index = (typeof options.index === 'string' || options.index instanceof String) ? options.index : "index.html"
options.last = (typeof opts.last === 'boolean') ? opts.last : true
const log = options.log || false
const rootPath = normalize(options.rootPath ? options.rootPath + "/" : "/")
const forbidden = opts.forbidden || [];
return async (ctx, next) => {
assert(ctx, 'koa context required')
// skip if this is not a GET/HEAD request
if (ctx.method !== 'HEAD' && ctx.method !== 'GET') {
return next()
}
let path = ctx.path
// Redirect non-slashed request to slashed, eg. /doc to /doc/
if (path + '/' === rootPath) {
return ctx.redirect(rootPath)
}
// Check if request path (eg: /doc/file.html) is allowed (eg. in /doc)
if (path.indexOf(rootPath) !== 0) {
return next()
}
/* Serve folders as specified
eg. for options:
rootDir = 'web/static'
rootPath = '/static'
'web/static/file.txt' will be served as 'http://server/static/file.txt'
*/
path = normalize(path.replace(rootPath, "/"))
/**
* LOG
*/
log && console.log(new Date().toISOString(), path)
/**
* If folder is in forbidden list, refuse request
*/
if (forbidden.length > 0) {
for (let folder of forbidden) {
folder = new RegExp(`\/${folder}\/`, 'i');
if (folder.test(path)) {
ctx.status = 403;
ctx.body = "FORBIDDEN FOLDER"
return (options.last) ? undefined : next()
}
}
}
let sent
/* In case of error from koa-send try to serve the default static file
eg. 404 error page or image that illustrates error
*/
try {
sent = await send(ctx, path, options)
} catch (error) {
if (!options.notFoundFile) {
if (options.last)
ctx.throw(404)
} else {
sent = await send(ctx, options.notFoundFile, options)
}
}
if (sent && options.last) {
return
} else {
return next()
}
}
}