-
Notifications
You must be signed in to change notification settings - Fork 0
/
serve-from-file-system.js
65 lines (56 loc) · 1.54 KB
/
serve-from-file-system.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
import path from 'node:path'
import fs from 'node:fs'
import parseUrl from 'url-parse'
import contentType from 'content-type'
import mime from 'mime'
import fresh from 'fresh'
export default function serveFromFileSystem(rootDirectory, baseUrl = '/') {
rootDirectory = path.resolve(rootDirectory)
return (next) => async (request) => {
const {pathname} = parseUrl(request.url)
if (path.relative(baseUrl, pathname).startsWith('../')) {
return next(request)
}
const filePath = path.join(rootDirectory, path.relative(baseUrl, pathname))
try {
return await serveFile(request, filePath)
} catch (error) {
if (error.code === 'ENOENT') {
return next(request)
}
throw error
}
}
}
async function serveFile(request, filePath) {
const fileStats = await fs.promises.stat(filePath)
if (fileStats.isDirectory()) {
return serveFile(request, path.join(filePath, 'index.html'))
}
const responseHeaders = {
'content-length': `${fileStats.size}`,
'content-type': contentType.format({
type: mime.getType(path.extname(filePath)),
parameters: {
charset: 'utf-8',
},
}),
'cache-control': 'no-cache',
'last-modified': new Date(fileStats.mtime).toUTCString(),
}
if (fresh(request.headers, responseHeaders)) {
return {
status: 304,
headers: {
...responseHeaders,
'content-length': '0',
},
body: '',
}
}
return {
status: 200,
headers: responseHeaders,
body: fs.createReadStream(filePath),
}
}