-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsend.js
69 lines (56 loc) · 1.79 KB
/
send.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
const fs = require('node:fs');
const { extname } = require('node:path');
const mime = require('mime-types');
const debug = require('debug')('@ladjs/koa-better-static:send');
module.exports = send;
async function send(ctx, path, opts) {
if (typeof ctx !== 'object') throw new Error('`ctx` is required');
if (typeof path !== 'string') throw new Error('`path` is required');
if (typeof opts !== 'object') throw new Error('`opts` is required');
// Options
debug('send "%s" %j', path, opts);
const { index, maxage, format, ifModifiedSinceSupport } = opts;
// Stat
let stats;
try {
stats = await fs.promises.stat(path);
} catch (err) {
const notfound = ['ENOENT', 'ENAMETOOLONG', 'ENOTDIR'];
if (notfound.includes(err.code)) {
return;
}
err.status = 500;
throw err;
}
// Format the path to serve static file servers
// and not require a trailing slash for directories,
// so that you can do both `/directory` and `/directory/`
if (stats.isDirectory()) {
if (format && index) {
path += '/' + index;
stats = await fs.promises.stat(path);
} else {
return;
}
}
// eslint-disable-next-line no-bitwise,unicorn/prefer-math-trunc
ctx.set('Cache-Control', 'max-age=' + ((maxage / 1000) | 0));
// Check if we can return a cache hit
if (ifModifiedSinceSupport) {
const ims = ctx.get('If-Modified-Since');
const ms = Date.parse(ims);
if (
ms &&
Math.floor(ms / 1000) === Math.floor(stats.mtime.getTime() / 1000)
) {
ctx.status = 304; // Not modified
return path;
}
}
// Stream
ctx.set('Last-Modified', stats.mtime.toUTCString());
ctx.set('Content-Length', stats.size);
if (!ctx.type) ctx.type = mime.contentType(extname(path));
ctx.body = fs.createReadStream(path);
return path;
}