Frontend/25_02_24/node_modules/@tinyhttp/send/dist/sendFile.js
2025-02-25 09:55:29 +01:00

67 lines
2.5 KiB
JavaScript

import { createReadStream, statSync } from 'node:fs';
import { extname, isAbsolute } from 'node:path';
import { join } from 'node:path';
import mime from 'mime';
import { createETag } from './utils.js';
export const enableCaching = (res, caching) => {
let cc = caching.maxAge != null && `public,max-age=${caching.maxAge}`;
if (cc && caching.immutable)
cc += ',immutable';
else if (cc && caching.maxAge === 0)
cc += ',must-revalidate';
if (cc)
res.setHeader('Cache-Control', cc);
};
/**
* Sends a file by piping a stream to response.
*
* It also checks for extension to set a proper `Content-Type` header.
*
* Path argument must be absolute. To use a relative path, specify the `root` option first.
*
* @param res Response
*/
export const sendFile = (req, res) => (path, opts = {}, cb) => {
const { root, headers = {}, encoding = 'utf-8', caching, ...options } = opts;
if (!isAbsolute(path) && !root)
throw new TypeError('path must be absolute');
if (caching)
enableCaching(res, caching);
const filePath = root ? join(root, path) : path;
const stats = statSync(filePath);
headers['Content-Encoding'] = encoding;
headers['Last-Modified'] = stats.mtime.toUTCString();
headers.ETag = createETag(stats, encoding);
if (!res.getHeader('Content-Type'))
headers['Content-Type'] = `${mime.getType(extname(path))}; charset=utf-8`;
let status = res.statusCode || 200;
if (req.headers.range) {
status = 206;
const [x, y] = req.headers.range.replace('bytes=', '').split('-');
const end = (options.end = Number.parseInt(y, 10) || stats.size - 1);
const start = (options.start = Number.parseInt(x, 10) || 0);
if (start >= stats.size || end >= stats.size) {
res
.writeHead(416, {
'Content-Range': `bytes */${stats.size}`
})
.end();
return res;
}
headers['Content-Range'] = `bytes ${start}-${end}/${stats.size}`;
headers['Content-Length'] = end - start + 1;
headers['Accept-Ranges'] = 'bytes';
}
else {
headers['Content-Length'] = stats.size;
}
for (const [k, v] of Object.entries(headers))
res.setHeader(k, v);
res.writeHead(status, headers);
const stream = createReadStream(filePath, options);
if (cb)
stream.on('error', (err) => cb(err)).on('end', () => cb());
stream.pipe(res);
return res;
};
//# sourceMappingURL=sendFile.js.map