@wooksjs/http-static 0.7.11 → 0.7.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +40 -30
- package/dist/index.mjs +18 -14
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
2
3
|
var __create = Object.create;
|
|
3
4
|
var __defProp = Object.defineProperty;
|
|
4
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -6,12 +7,16 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
6
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
9
|
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function")
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
12
|
+
key = keys[i];
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
14
|
+
__defProp(to, key, {
|
|
15
|
+
get: ((k) => from[k]).bind(null, key),
|
|
16
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
15
20
|
}
|
|
16
21
|
return to;
|
|
17
22
|
};
|
|
@@ -21,9 +26,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
26
|
}) : target, mod));
|
|
22
27
|
|
|
23
28
|
//#endregion
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
let _wooksjs_event_http = require("@wooksjs/event-http");
|
|
30
|
+
let fs = require("fs");
|
|
31
|
+
let path = require("path");
|
|
32
|
+
path = __toESM(path);
|
|
27
33
|
|
|
28
34
|
//#region packages/http-static/src/mime/extensions.ts
|
|
29
35
|
const extensions = {
|
|
@@ -1212,9 +1218,8 @@ const extensions = {
|
|
|
1212
1218
|
|
|
1213
1219
|
//#endregion
|
|
1214
1220
|
//#region packages/http-static/src/mime/index.ts
|
|
1215
|
-
function getMimeType(path
|
|
1216
|
-
|
|
1217
|
-
return extensions[ext] || fallback;
|
|
1221
|
+
function getMimeType(path, fallback = null) {
|
|
1222
|
+
return extensions[(/\.([^.]+)$/u.exec(path) || [])[1] || path] || fallback;
|
|
1218
1223
|
}
|
|
1219
1224
|
|
|
1220
1225
|
//#endregion
|
|
@@ -1247,26 +1252,25 @@ const { stat, readdir } = fs.promises;
|
|
|
1247
1252
|
* @returns A readable stream, string body, or HTML directory listing.
|
|
1248
1253
|
*/
|
|
1249
1254
|
async function serveFile(filePath, options = {}) {
|
|
1250
|
-
const response = (0,
|
|
1251
|
-
const headers = (0,
|
|
1252
|
-
const { method, url } = (0,
|
|
1255
|
+
const response = (0, _wooksjs_event_http.useResponse)();
|
|
1256
|
+
const headers = (0, _wooksjs_event_http.useHeaders)();
|
|
1257
|
+
const { method, url } = (0, _wooksjs_event_http.useRequest)();
|
|
1253
1258
|
const normalizedPath = normalizePath(filePath, options.baseDir);
|
|
1254
1259
|
if (!options.allowDotDot) {
|
|
1255
1260
|
const resolvedBase = path.default.resolve(options.baseDir || process.cwd());
|
|
1256
|
-
if (!normalizedPath.startsWith(resolvedBase + path.default.sep) && normalizedPath !== resolvedBase) throw new
|
|
1261
|
+
if (!normalizedPath.startsWith(resolvedBase + path.default.sep) && normalizedPath !== resolvedBase) throw new _wooksjs_event_http.HttpError(403, "Path traversal is not allowed");
|
|
1257
1262
|
}
|
|
1258
1263
|
let fileStats;
|
|
1259
1264
|
try {
|
|
1260
1265
|
fileStats = await stat(normalizedPath);
|
|
1261
1266
|
} catch {
|
|
1262
1267
|
if (options.defaultExt) {
|
|
1263
|
-
|
|
1264
|
-
if (!ext) return serveFile(`${filePath}.${options.defaultExt}`, {
|
|
1268
|
+
if (!path.default.extname(filePath)) return serveFile(`${filePath}.${options.defaultExt}`, {
|
|
1265
1269
|
...options,
|
|
1266
1270
|
defaultExt: void 0
|
|
1267
1271
|
});
|
|
1268
1272
|
}
|
|
1269
|
-
throw new
|
|
1273
|
+
throw new _wooksjs_event_http.HttpError(404);
|
|
1270
1274
|
}
|
|
1271
1275
|
response.status = 200;
|
|
1272
1276
|
const etag = `"${[
|
|
@@ -1295,24 +1299,22 @@ async function serveFile(filePath, options = {}) {
|
|
|
1295
1299
|
}
|
|
1296
1300
|
response.removeHeader("etag");
|
|
1297
1301
|
response.removeHeader("last-modified");
|
|
1298
|
-
throw new
|
|
1302
|
+
throw new _wooksjs_event_http.HttpError(404);
|
|
1299
1303
|
}
|
|
1300
1304
|
let range = headers.range;
|
|
1301
1305
|
let start;
|
|
1302
1306
|
let end;
|
|
1303
1307
|
let size = fileStats.size;
|
|
1304
1308
|
if (range) {
|
|
1305
|
-
const
|
|
1306
|
-
const [s, e] = rangeParts;
|
|
1309
|
+
const [s, e] = range.trim().replace(/bytes=/u, "").split("-");
|
|
1307
1310
|
start = Number.parseInt(s, 10);
|
|
1308
1311
|
end = e ? Number.parseInt(e, 10) : size - 1;
|
|
1309
1312
|
end = Math.min(size - 1, end);
|
|
1310
|
-
if (start > end || Number.isNaN(start) || Number.isNaN(end)) throw new
|
|
1313
|
+
if (start > end || Number.isNaN(start) || Number.isNaN(end)) throw new _wooksjs_event_http.HttpError(416);
|
|
1311
1314
|
size = end - start + 1;
|
|
1312
1315
|
const ifRange = headers["if-range"] || "";
|
|
1313
1316
|
const ifRangeTag = ifRange.startsWith("\"") ? ifRange : "";
|
|
1314
|
-
|
|
1315
|
-
if (ifRange && !isNotModified(etag, lastModified, ifRangeTag, ifRangeDate)) {
|
|
1317
|
+
if (ifRange && !isNotModified(etag, lastModified, ifRangeTag, ifRangeTag ? "" : ifRange)) {
|
|
1316
1318
|
response.status = 200;
|
|
1317
1319
|
size = fileStats.size;
|
|
1318
1320
|
range = "";
|
|
@@ -1341,8 +1343,8 @@ function isNotModified(etag, lastModified, clientEtag, clientLM) {
|
|
|
1341
1343
|
return false;
|
|
1342
1344
|
}
|
|
1343
1345
|
async function listDirectory(dirPath) {
|
|
1344
|
-
const response = (0,
|
|
1345
|
-
const { url } = (0,
|
|
1346
|
+
const response = (0, _wooksjs_event_http.useResponse)();
|
|
1347
|
+
const { url } = (0, _wooksjs_event_http.useRequest)();
|
|
1346
1348
|
const list = await readdir(dirPath);
|
|
1347
1349
|
const promises = [];
|
|
1348
1350
|
let detailedList = [];
|
|
@@ -1365,8 +1367,16 @@ async function listDirectory(dirPath) {
|
|
|
1365
1367
|
dir: true
|
|
1366
1368
|
});
|
|
1367
1369
|
response.setContentType("text/html");
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
+
return `<html><head><title>Dir</title> <style type="text/css">
|
|
1371
|
+
html { font-family: monospace }
|
|
1372
|
+
span { padding: 0px 2px }
|
|
1373
|
+
.text { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; }
|
|
1374
|
+
.icon { width: 20px; display: inline-block; text-align: center; }
|
|
1375
|
+
.name { width: 250px; display: inline-block; }
|
|
1376
|
+
.size { width: 80px; display: inline-block; color: grey; text-align: right; }
|
|
1377
|
+
.date { width: 200px; display: inline-block; color: grey; text-align: right; }
|
|
1378
|
+
|
|
1379
|
+
</style> </head><body><ul>${detailedList.map((d) => `<li> <span class="icon">${d.dir ? "📁" : "🗎"}</span><a href="${escapeHtml(path.default.join(url || "", d.name))}"><span class="name text">${escapeHtml(d.name)}</span></a><span class="size text">${d.size && (d.size > 1e4 ? `${Math.round(d.size / 1024 / 1024).toString()}Mb` : `${Math.round(d.size / 1024).toString()}Kb`) || ""}</span><span class="date text">${d.mtime && d.mtime.toISOString() || ""}</li>`).join("\n")}</ul></body></html>`;
|
|
1370
1380
|
}
|
|
1371
1381
|
|
|
1372
1382
|
//#endregion
|
package/dist/index.mjs
CHANGED
|
@@ -1189,9 +1189,8 @@ const extensions = {
|
|
|
1189
1189
|
|
|
1190
1190
|
//#endregion
|
|
1191
1191
|
//#region packages/http-static/src/mime/index.ts
|
|
1192
|
-
function getMimeType(path
|
|
1193
|
-
|
|
1194
|
-
return extensions[ext] || fallback;
|
|
1192
|
+
function getMimeType(path, fallback = null) {
|
|
1193
|
+
return extensions[(/\.([^.]+)$/u.exec(path) || [])[1] || path] || fallback;
|
|
1195
1194
|
}
|
|
1196
1195
|
|
|
1197
1196
|
//#endregion
|
|
@@ -1237,8 +1236,7 @@ async function serveFile(filePath, options = {}) {
|
|
|
1237
1236
|
fileStats = await stat(normalizedPath);
|
|
1238
1237
|
} catch {
|
|
1239
1238
|
if (options.defaultExt) {
|
|
1240
|
-
|
|
1241
|
-
if (!ext) return serveFile(`${filePath}.${options.defaultExt}`, {
|
|
1239
|
+
if (!path.extname(filePath)) return serveFile(`${filePath}.${options.defaultExt}`, {
|
|
1242
1240
|
...options,
|
|
1243
1241
|
defaultExt: void 0
|
|
1244
1242
|
});
|
|
@@ -1279,8 +1277,7 @@ async function serveFile(filePath, options = {}) {
|
|
|
1279
1277
|
let end;
|
|
1280
1278
|
let size = fileStats.size;
|
|
1281
1279
|
if (range) {
|
|
1282
|
-
const
|
|
1283
|
-
const [s, e] = rangeParts;
|
|
1280
|
+
const [s, e] = range.trim().replace(/bytes=/u, "").split("-");
|
|
1284
1281
|
start = Number.parseInt(s, 10);
|
|
1285
1282
|
end = e ? Number.parseInt(e, 10) : size - 1;
|
|
1286
1283
|
end = Math.min(size - 1, end);
|
|
@@ -1288,8 +1285,7 @@ async function serveFile(filePath, options = {}) {
|
|
|
1288
1285
|
size = end - start + 1;
|
|
1289
1286
|
const ifRange = headers["if-range"] || "";
|
|
1290
1287
|
const ifRangeTag = ifRange.startsWith("\"") ? ifRange : "";
|
|
1291
|
-
|
|
1292
|
-
if (ifRange && !isNotModified(etag, lastModified, ifRangeTag, ifRangeDate)) {
|
|
1288
|
+
if (ifRange && !isNotModified(etag, lastModified, ifRangeTag, ifRangeTag ? "" : ifRange)) {
|
|
1293
1289
|
response.status = 200;
|
|
1294
1290
|
size = fileStats.size;
|
|
1295
1291
|
range = "";
|
|
@@ -1321,13 +1317,13 @@ async function listDirectory(dirPath) {
|
|
|
1321
1317
|
const response = useResponse();
|
|
1322
1318
|
const { url } = useRequest();
|
|
1323
1319
|
const list = await readdir(dirPath);
|
|
1324
|
-
const promises
|
|
1320
|
+
const promises = [];
|
|
1325
1321
|
let detailedList = [];
|
|
1326
|
-
for (const item of list) promises
|
|
1322
|
+
for (const item of list) promises.push({
|
|
1327
1323
|
name: item,
|
|
1328
1324
|
promise: stat(path.join(dirPath, item))
|
|
1329
1325
|
});
|
|
1330
|
-
for (const item of promises
|
|
1326
|
+
for (const item of promises) {
|
|
1331
1327
|
const data = await item.promise;
|
|
1332
1328
|
detailedList.push({
|
|
1333
1329
|
name: item.name,
|
|
@@ -1342,8 +1338,16 @@ async function listDirectory(dirPath) {
|
|
|
1342
1338
|
dir: true
|
|
1343
1339
|
});
|
|
1344
1340
|
response.setContentType("text/html");
|
|
1345
|
-
|
|
1346
|
-
|
|
1341
|
+
return `<html><head><title>Dir</title> <style type="text/css">
|
|
1342
|
+
html { font-family: monospace }
|
|
1343
|
+
span { padding: 0px 2px }
|
|
1344
|
+
.text { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; }
|
|
1345
|
+
.icon { width: 20px; display: inline-block; text-align: center; }
|
|
1346
|
+
.name { width: 250px; display: inline-block; }
|
|
1347
|
+
.size { width: 80px; display: inline-block; color: grey; text-align: right; }
|
|
1348
|
+
.date { width: 200px; display: inline-block; color: grey; text-align: right; }
|
|
1349
|
+
|
|
1350
|
+
</style> </head><body><ul>${detailedList.map((d) => `<li> <span class="icon">${d.dir ? "📁" : "🗎"}</span><a href="${escapeHtml(path.join(url || "", d.name))}"><span class="name text">${escapeHtml(d.name)}</span></a><span class="size text">${d.size && (d.size > 1e4 ? `${Math.round(d.size / 1024 / 1024).toString()}Mb` : `${Math.round(d.size / 1024).toString()}Kb`) || ""}</span><span class="date text">${d.mtime && d.mtime.toISOString() || ""}</li>`).join("\n")}</ul></body></html>`;
|
|
1347
1351
|
}
|
|
1348
1352
|
|
|
1349
1353
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wooksjs/http-static",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.12",
|
|
4
4
|
"description": "@wooksjs/http-static",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api",
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"typescript": "^5.9.3",
|
|
44
44
|
"vitest": "^3.2.4",
|
|
45
|
-
"@wooksjs/event-http": "^0.7.
|
|
45
|
+
"@wooksjs/event-http": "^0.7.12"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
|
-
"@wooksjs/event-http": "^0.7.
|
|
48
|
+
"@wooksjs/event-http": "^0.7.12"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "rolldown -c ../../rolldown.config.mjs"
|