static.js 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.uniStaticMiddleware = void 0;
  7. const fs_1 = __importDefault(require("fs"));
  8. const url_1 = __importDefault(require("url"));
  9. const lite_1 = __importDefault(require("mime/lite"));
  10. function normalizeFile(filename, isEtag) {
  11. const stats = fs_1.default.statSync(filename);
  12. return {
  13. stats,
  14. headers: normalizeHeaders(filename, stats, isEtag),
  15. };
  16. }
  17. function normalizeHeaders(filename, stats, isEtag) {
  18. const headers = {
  19. 'Content-Length': stats.size,
  20. 'Content-Type': lite_1.default.getType(filename) || '',
  21. 'Last-Modified': stats.mtime.toUTCString(),
  22. };
  23. if (isEtag) {
  24. headers['ETag'] = `W/"${stats.size}-${stats.mtime.getTime()}"`;
  25. }
  26. return headers;
  27. }
  28. function send(req, res, filename, stats, headers) {
  29. let code = 200;
  30. headers = { ...headers };
  31. const opts = {};
  32. for (const key in headers) {
  33. const value = res.getHeader(key);
  34. if (value) {
  35. headers[key] = value;
  36. }
  37. }
  38. if (res.getHeader('content-type')) {
  39. headers['Content-Type'] = res.getHeader('content-type');
  40. }
  41. if (req.headers.range) {
  42. code = 206;
  43. const [x, y] = req.headers.range.replace('bytes=', '').split('-');
  44. const end = (opts.end = parseInt(y, 10) || stats.size - 1);
  45. const start = (opts.start = parseInt(x, 10) || 0);
  46. if (start >= stats.size || end >= stats.size) {
  47. res.setHeader('Content-Range', `bytes */${stats.size}`);
  48. res.statusCode = 416;
  49. return res.end();
  50. }
  51. headers['Content-Range'] = `bytes ${start}-${end}/${stats.size}`;
  52. headers['Content-Length'] = end - start + 1;
  53. headers['Accept-Ranges'] = 'bytes';
  54. }
  55. res.writeHead(code, headers);
  56. fs_1.default.createReadStream(filename, opts).pipe(res);
  57. }
  58. function uniStaticMiddleware(opts) {
  59. const isEtag = !!opts.etag;
  60. return function staticMiddleware(req, res, next) {
  61. const pathname = url_1.default.parse(req.url).pathname;
  62. if (!pathname) {
  63. return next();
  64. }
  65. const filename = opts.resolve(pathname);
  66. if (!filename) {
  67. return next();
  68. }
  69. const data = normalizeFile(filename, isEtag);
  70. if (!data) {
  71. return next();
  72. }
  73. if (isEtag && req.headers['if-none-match'] === data.headers['ETag']) {
  74. res.writeHead(304);
  75. return res.end();
  76. }
  77. return send(req, res, filename, data.stats, data.headers);
  78. };
  79. }
  80. exports.uniStaticMiddleware = uniStaticMiddleware;