oblien 2.2.37 → 2.2.38
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/README.md +2 -0
- package/dist/cdn.d.ts +105 -0
- package/dist/cdn.d.ts.map +1 -0
- package/dist/cdn.js +201 -0
- package/dist/cdn.js.map +1 -0
- package/dist/cli/commands/cdn.d.ts +3 -0
- package/dist/cli/commands/cdn.d.ts.map +1 -0
- package/dist/cli/commands/cdn.js +216 -0
- package/dist/cli/commands/cdn.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +17 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +113 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/tunnel.d.ts +1 -0
- package/dist/cli/commands/tunnel.d.ts.map +1 -1
- package/dist/cli/commands/tunnel.js +100 -3
- package/dist/cli/commands/tunnel.js.map +1 -1
- package/dist/cli/index.js +14 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/client.d.ts +5 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +7 -0
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +48 -0
- package/dist/mcp/tools.js.map +1 -1
- package/dist/runtime/proxy.d.ts +55 -0
- package/dist/runtime/proxy.d.ts.map +1 -0
- package/dist/runtime/proxy.js +79 -0
- package/dist/runtime/proxy.js.map +1 -0
- package/dist/runtime.d.ts +16 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +18 -0
- package/dist/runtime.js.map +1 -1
- package/dist/server/static.d.ts +81 -0
- package/dist/server/static.d.ts.map +1 -0
- package/dist/server/static.js +465 -0
- package/dist/server/static.js.map +1 -0
- package/dist/types/cdn.d.ts +301 -0
- package/dist/types/cdn.d.ts.map +1 -0
- package/dist/types/cdn.js +10 -0
- package/dist/types/cdn.js.map +1 -0
- package/dist/types/client.d.ts +10 -0
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/docs/cdn.md +119 -0
- package/docs/runtime.md +30 -0
- package/docs/serve.md +84 -0
- package/package.json +1 -1
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static file server — a small, dependency-free HTTP server for a folder.
|
|
3
|
+
*
|
|
4
|
+
* Built entirely on Node's `http`/`fs`/`path`, so it adds nothing to the SDK's
|
|
5
|
+
* dependency tree. Pair it with the {@link TunnelClient} (or `oblien serve`) to
|
|
6
|
+
* put a folder on the public internet in one step.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { startStaticServer } from 'oblien';
|
|
10
|
+
*
|
|
11
|
+
* const site = await startStaticServer({ root: './public', spa: true });
|
|
12
|
+
* console.log(`serving on ${site.url}`);
|
|
13
|
+
* // ... later
|
|
14
|
+
* await site.close();
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* Features: streamed responses (memory-safe for large files), correct MIME
|
|
18
|
+
* types, `Range` requests (media seeking), `ETag`/`Last-Modified` revalidation
|
|
19
|
+
* (`304`), directory `index.html`, optional directory listings, optional SPA
|
|
20
|
+
* fallback, and strict path-traversal protection.
|
|
21
|
+
*/
|
|
22
|
+
import { createServer } from 'node:http';
|
|
23
|
+
import { createReadStream, realpathSync } from 'node:fs';
|
|
24
|
+
import { stat, readdir, realpath } from 'node:fs/promises';
|
|
25
|
+
import { join, normalize, resolve, sep, extname } from 'node:path';
|
|
26
|
+
/** Extension → Content-Type. Text types carry an explicit charset. */
|
|
27
|
+
const MIME = {
|
|
28
|
+
'.html': 'text/html; charset=utf-8',
|
|
29
|
+
'.htm': 'text/html; charset=utf-8',
|
|
30
|
+
'.css': 'text/css; charset=utf-8',
|
|
31
|
+
'.js': 'text/javascript; charset=utf-8',
|
|
32
|
+
'.mjs': 'text/javascript; charset=utf-8',
|
|
33
|
+
'.cjs': 'text/javascript; charset=utf-8',
|
|
34
|
+
'.json': 'application/json; charset=utf-8',
|
|
35
|
+
'.map': 'application/json; charset=utf-8',
|
|
36
|
+
'.txt': 'text/plain; charset=utf-8',
|
|
37
|
+
'.md': 'text/markdown; charset=utf-8',
|
|
38
|
+
'.xml': 'application/xml; charset=utf-8',
|
|
39
|
+
'.csv': 'text/csv; charset=utf-8',
|
|
40
|
+
'.svg': 'image/svg+xml',
|
|
41
|
+
'.png': 'image/png',
|
|
42
|
+
'.jpg': 'image/jpeg',
|
|
43
|
+
'.jpeg': 'image/jpeg',
|
|
44
|
+
'.gif': 'image/gif',
|
|
45
|
+
'.webp': 'image/webp',
|
|
46
|
+
'.avif': 'image/avif',
|
|
47
|
+
'.ico': 'image/x-icon',
|
|
48
|
+
'.bmp': 'image/bmp',
|
|
49
|
+
'.woff': 'font/woff',
|
|
50
|
+
'.woff2': 'font/woff2',
|
|
51
|
+
'.ttf': 'font/ttf',
|
|
52
|
+
'.otf': 'font/otf',
|
|
53
|
+
'.eot': 'application/vnd.ms-fontobject',
|
|
54
|
+
'.mp4': 'video/mp4',
|
|
55
|
+
'.webm': 'video/webm',
|
|
56
|
+
'.ogg': 'audio/ogg',
|
|
57
|
+
'.mp3': 'audio/mpeg',
|
|
58
|
+
'.wav': 'audio/wav',
|
|
59
|
+
'.wasm': 'application/wasm',
|
|
60
|
+
'.pdf': 'application/pdf',
|
|
61
|
+
'.zip': 'application/zip',
|
|
62
|
+
};
|
|
63
|
+
function contentType(path) {
|
|
64
|
+
return MIME[extname(path).toLowerCase()] || 'application/octet-stream';
|
|
65
|
+
}
|
|
66
|
+
/** Weak-ish validator tag derived from size + mtime — cheap and stable per file. */
|
|
67
|
+
function etagFor(size, mtimeMs) {
|
|
68
|
+
return `"${size.toString(16)}-${Math.floor(mtimeMs).toString(16)}"`;
|
|
69
|
+
}
|
|
70
|
+
function escapeHtml(s) {
|
|
71
|
+
return s
|
|
72
|
+
.replace(/&/g, '&')
|
|
73
|
+
.replace(/</g, '<')
|
|
74
|
+
.replace(/>/g, '>')
|
|
75
|
+
.replace(/"/g, '"')
|
|
76
|
+
.replace(/'/g, ''');
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Parse a single-range `Range` header (`bytes=start-end`) against a known size.
|
|
80
|
+
* Returns the resolved `[start, end]` (inclusive), `null` when there's no usable
|
|
81
|
+
* range header, or `'invalid'` when the range is unsatisfiable (→ 416).
|
|
82
|
+
*/
|
|
83
|
+
function parseRange(header, size) {
|
|
84
|
+
if (!header || !header.startsWith('bytes='))
|
|
85
|
+
return null;
|
|
86
|
+
const specs = header.slice(6).split(',');
|
|
87
|
+
// We only speak single-part ranges. For a multi-range request, ignore Range
|
|
88
|
+
// and let the caller send the full 200 (RFC 7233 allows this) rather than
|
|
89
|
+
// returning a misleading single-part 206 that answers only the first range.
|
|
90
|
+
if (specs.length > 1)
|
|
91
|
+
return null;
|
|
92
|
+
const spec = specs[0]?.trim();
|
|
93
|
+
if (!spec)
|
|
94
|
+
return null;
|
|
95
|
+
const dash = spec.indexOf('-');
|
|
96
|
+
if (dash < 0)
|
|
97
|
+
return 'invalid';
|
|
98
|
+
const startRaw = spec.slice(0, dash).trim();
|
|
99
|
+
const endRaw = spec.slice(dash + 1).trim();
|
|
100
|
+
let start;
|
|
101
|
+
let end;
|
|
102
|
+
if (startRaw === '') {
|
|
103
|
+
// Suffix range: last N bytes.
|
|
104
|
+
const suffix = Number(endRaw);
|
|
105
|
+
if (!Number.isFinite(suffix) || suffix <= 0)
|
|
106
|
+
return 'invalid';
|
|
107
|
+
start = Math.max(0, size - suffix);
|
|
108
|
+
end = size - 1;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
start = Number(startRaw);
|
|
112
|
+
end = endRaw === '' ? size - 1 : Number(endRaw);
|
|
113
|
+
if (!Number.isFinite(start) || !Number.isFinite(end))
|
|
114
|
+
return 'invalid';
|
|
115
|
+
if (end > size - 1)
|
|
116
|
+
end = size - 1;
|
|
117
|
+
}
|
|
118
|
+
if (start > end || start < 0 || start >= size)
|
|
119
|
+
return 'invalid';
|
|
120
|
+
return [start, end];
|
|
121
|
+
}
|
|
122
|
+
function sendText(res, status, message) {
|
|
123
|
+
const body = Buffer.from(message + '\n');
|
|
124
|
+
res.writeHead(status, {
|
|
125
|
+
'Content-Type': 'text/plain; charset=utf-8',
|
|
126
|
+
'Content-Length': body.length,
|
|
127
|
+
});
|
|
128
|
+
res.end(body);
|
|
129
|
+
}
|
|
130
|
+
/** Render a minimal, self-contained directory listing page. */
|
|
131
|
+
function renderListing(urlPath, entries) {
|
|
132
|
+
const rows = entries
|
|
133
|
+
.sort((a, b) => (a.dir === b.dir ? a.name.localeCompare(b.name) : a.dir ? -1 : 1))
|
|
134
|
+
.map(e => {
|
|
135
|
+
const label = escapeHtml(e.name) + (e.dir ? '/' : '');
|
|
136
|
+
const href = encodeURIComponent(e.name) + (e.dir ? '/' : '');
|
|
137
|
+
return ` <li><a href="${href}">${label}</a></li>`;
|
|
138
|
+
})
|
|
139
|
+
.join('\n');
|
|
140
|
+
const parent = urlPath === '/' ? '' : ' <li><a href="../">../</a></li>\n';
|
|
141
|
+
const html = `<!doctype html>
|
|
142
|
+
<html lang="en">
|
|
143
|
+
<head>
|
|
144
|
+
<meta charset="utf-8">
|
|
145
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
146
|
+
<title>Index of ${escapeHtml(urlPath)}</title>
|
|
147
|
+
<style>
|
|
148
|
+
body { font: 14px/1.6 ui-monospace, SFMono-Regular, Menlo, monospace; margin: 2rem auto; max-width: 48rem; padding: 0 1rem; color: #1a1a1a; }
|
|
149
|
+
h1 { font-size: 1rem; font-weight: 600; border-bottom: 1px solid #eee; padding-bottom: .5rem; }
|
|
150
|
+
ul { list-style: none; padding: 0; }
|
|
151
|
+
li { padding: .1rem 0; }
|
|
152
|
+
a { color: #0b6cff; text-decoration: none; }
|
|
153
|
+
a:hover { text-decoration: underline; }
|
|
154
|
+
@media (prefers-color-scheme: dark) { body { background:#111; color:#eee; } h1 { border-color:#333; } a { color:#6ea8ff; } }
|
|
155
|
+
</style>
|
|
156
|
+
</head>
|
|
157
|
+
<body>
|
|
158
|
+
<h1>Index of ${escapeHtml(urlPath)}</h1>
|
|
159
|
+
<ul>
|
|
160
|
+
${parent}${rows}
|
|
161
|
+
</ul>
|
|
162
|
+
</body>
|
|
163
|
+
</html>
|
|
164
|
+
`;
|
|
165
|
+
return Buffer.from(html);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Build the request handler for a static root. Exposed so callers can mount it
|
|
169
|
+
* on an existing server if they prefer; most callers want {@link startStaticServer}.
|
|
170
|
+
*/
|
|
171
|
+
export function createStaticHandler(options) {
|
|
172
|
+
const root = resolve(options.root);
|
|
173
|
+
// Canonical root for symlink-escape checks. Falls back to the lexical root if
|
|
174
|
+
// it can't be resolved (e.g. the dir doesn't exist yet).
|
|
175
|
+
let realRoot;
|
|
176
|
+
try {
|
|
177
|
+
realRoot = realpathSync(root);
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
realRoot = root;
|
|
181
|
+
}
|
|
182
|
+
const indexFile = options.index ?? 'index.html';
|
|
183
|
+
const listing = options.listing ?? true;
|
|
184
|
+
const spa = options.spa ?? false;
|
|
185
|
+
const allowDotfiles = options.allowDotfiles ?? false;
|
|
186
|
+
const onRequest = options.onRequest;
|
|
187
|
+
const report = (req, res) => {
|
|
188
|
+
if (!onRequest)
|
|
189
|
+
return;
|
|
190
|
+
onRequest({ method: req.method ?? 'GET', path: reqPath(req), status: res.statusCode });
|
|
191
|
+
};
|
|
192
|
+
const reqPath = (req) => {
|
|
193
|
+
try {
|
|
194
|
+
return decodeURIComponent(new URL(req.url ?? '/', 'http://localhost').pathname);
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return req.url ?? '/';
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
return (req, res) => {
|
|
201
|
+
res.on('finish', () => report(req, res));
|
|
202
|
+
const method = req.method ?? 'GET';
|
|
203
|
+
if (method !== 'GET' && method !== 'HEAD') {
|
|
204
|
+
res.setHeader('Allow', 'GET, HEAD');
|
|
205
|
+
sendText(res, 405, 'Method Not Allowed');
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
let url;
|
|
209
|
+
try {
|
|
210
|
+
url = new URL(req.url ?? '/', 'http://localhost');
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
sendText(res, 400, 'Bad Request');
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
let pathname;
|
|
217
|
+
try {
|
|
218
|
+
pathname = decodeURIComponent(url.pathname);
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
sendText(res, 400, 'Bad Request');
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (pathname.includes('\0')) {
|
|
225
|
+
sendText(res, 400, 'Bad Request');
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
// Deny dotfiles/dot-directories (.git, .env, …) — hidden AND unservable by
|
|
229
|
+
// default, since this server is often published to the public internet.
|
|
230
|
+
if (!allowDotfiles && pathname.split('/').some(s => s.startsWith('.') && s !== '.well-known')) {
|
|
231
|
+
sendText(res, 404, 'Not Found');
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
// Resolve against root and confirm the result stays inside root.
|
|
235
|
+
const target = normalize(join(root, pathname));
|
|
236
|
+
if (target !== root && !target.startsWith(root + sep)) {
|
|
237
|
+
sendText(res, 403, 'Forbidden');
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
void serve(req, res, {
|
|
241
|
+
root,
|
|
242
|
+
realRoot,
|
|
243
|
+
target,
|
|
244
|
+
pathname,
|
|
245
|
+
indexFile,
|
|
246
|
+
listing,
|
|
247
|
+
spa,
|
|
248
|
+
search: url.search,
|
|
249
|
+
}).catch(() => {
|
|
250
|
+
// Last-resort guard: never let a request throw an unhandled rejection.
|
|
251
|
+
if (!res.headersSent)
|
|
252
|
+
sendText(res, 500, 'Internal Server Error');
|
|
253
|
+
else
|
|
254
|
+
res.destroy();
|
|
255
|
+
});
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Confirm a path's canonical location is still inside the served root, so a
|
|
260
|
+
* symlink inside the folder can't hand out files from elsewhere on the machine.
|
|
261
|
+
* Returns false if the path is gone or escapes the root.
|
|
262
|
+
*/
|
|
263
|
+
async function insideRoot(realRoot, p) {
|
|
264
|
+
try {
|
|
265
|
+
const rp = await realpath(p);
|
|
266
|
+
return rp === realRoot || rp.startsWith(realRoot + sep);
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
async function serve(req, res, ctx) {
|
|
273
|
+
let info;
|
|
274
|
+
try {
|
|
275
|
+
info = await stat(ctx.target);
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
return notFound(req, res, ctx);
|
|
279
|
+
}
|
|
280
|
+
if (info.isDirectory()) {
|
|
281
|
+
// Redirect `/dir` → `/dir/` so relative links inside resolve correctly.
|
|
282
|
+
if (!ctx.pathname.endsWith('/')) {
|
|
283
|
+
res.writeHead(301, { Location: encodeURI(ctx.pathname) + '/' + ctx.search });
|
|
284
|
+
res.end();
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const indexPath = join(ctx.target, ctx.indexFile);
|
|
288
|
+
try {
|
|
289
|
+
const idx = await stat(indexPath);
|
|
290
|
+
if (idx.isFile()) {
|
|
291
|
+
return sendFile(req, res, ctx.realRoot, indexPath, idx.size, idx.mtimeMs);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
/* no index — fall through to listing */
|
|
296
|
+
}
|
|
297
|
+
if (ctx.listing) {
|
|
298
|
+
return sendListing(req, res, ctx);
|
|
299
|
+
}
|
|
300
|
+
return sendText(res, 403, 'Forbidden');
|
|
301
|
+
}
|
|
302
|
+
if (info.isFile()) {
|
|
303
|
+
return sendFile(req, res, ctx.realRoot, ctx.target, info.size, info.mtimeMs);
|
|
304
|
+
}
|
|
305
|
+
// Sockets, FIFOs, etc. — not servable.
|
|
306
|
+
return notFound(req, res, ctx);
|
|
307
|
+
}
|
|
308
|
+
async function notFound(req, res, ctx) {
|
|
309
|
+
// SPA fallback: hand back the root index so client-side routing takes over.
|
|
310
|
+
if (ctx.spa) {
|
|
311
|
+
const indexPath = join(ctx.root, ctx.indexFile);
|
|
312
|
+
try {
|
|
313
|
+
const idx = await stat(indexPath);
|
|
314
|
+
if (idx.isFile()) {
|
|
315
|
+
return sendFile(req, res, ctx.realRoot, indexPath, idx.size, idx.mtimeMs, 200);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
/* no index to fall back to */
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
sendText(res, 404, 'Not Found');
|
|
323
|
+
}
|
|
324
|
+
async function sendListing(req, res, ctx) {
|
|
325
|
+
if (!(await insideRoot(ctx.realRoot, ctx.target))) {
|
|
326
|
+
return sendText(res, 404, 'Not Found');
|
|
327
|
+
}
|
|
328
|
+
let dirents;
|
|
329
|
+
try {
|
|
330
|
+
dirents = await readdir(ctx.target, { withFileTypes: true });
|
|
331
|
+
}
|
|
332
|
+
catch {
|
|
333
|
+
return sendText(res, 500, 'Internal Server Error');
|
|
334
|
+
}
|
|
335
|
+
const entries = dirents
|
|
336
|
+
.filter(d => !d.name.startsWith('.'))
|
|
337
|
+
.map(d => ({ name: d.name, dir: d.isDirectory() }));
|
|
338
|
+
const body = renderListing(ctx.pathname, entries);
|
|
339
|
+
res.writeHead(200, {
|
|
340
|
+
'Content-Type': 'text/html; charset=utf-8',
|
|
341
|
+
'Content-Length': body.length,
|
|
342
|
+
'Cache-Control': 'no-cache',
|
|
343
|
+
});
|
|
344
|
+
if ((req.method ?? 'GET') === 'HEAD') {
|
|
345
|
+
res.end();
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
res.end(body);
|
|
349
|
+
}
|
|
350
|
+
async function sendFile(req, res, realRoot, filePath, size, mtimeMs, forceStatus) {
|
|
351
|
+
// Reject files whose canonical path escapes the root (symlink out of folder).
|
|
352
|
+
if (!(await insideRoot(realRoot, filePath))) {
|
|
353
|
+
return sendText(res, 404, 'Not Found');
|
|
354
|
+
}
|
|
355
|
+
const etag = etagFor(size, mtimeMs);
|
|
356
|
+
const lastModified = new Date(mtimeMs).toUTCString();
|
|
357
|
+
const type = contentType(filePath);
|
|
358
|
+
const baseHeaders = {
|
|
359
|
+
'Content-Type': type,
|
|
360
|
+
'Last-Modified': lastModified,
|
|
361
|
+
ETag: etag,
|
|
362
|
+
'Accept-Ranges': 'bytes',
|
|
363
|
+
'Cache-Control': 'no-cache',
|
|
364
|
+
};
|
|
365
|
+
// Conditional request — revalidate without resending the body.
|
|
366
|
+
const inm = req.headers['if-none-match'];
|
|
367
|
+
const ims = req.headers['if-modified-since'];
|
|
368
|
+
const notModified = (inm && inm === etag) ||
|
|
369
|
+
(!inm && ims && !Number.isNaN(Date.parse(ims)) && Date.parse(ims) >= Math.floor(mtimeMs / 1000) * 1000);
|
|
370
|
+
if (!forceStatus && notModified) {
|
|
371
|
+
res.writeHead(304, baseHeaders);
|
|
372
|
+
res.end();
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
const method = req.method ?? 'GET';
|
|
376
|
+
// If-Range: only honor the Range when the client's validator still matches the
|
|
377
|
+
// current file. On a mismatch (the file changed since), fall back to a full 200
|
|
378
|
+
// so a resumed download can't stitch together two different versions.
|
|
379
|
+
const ifRange = req.headers['if-range'];
|
|
380
|
+
let rangeOk = true;
|
|
381
|
+
if (ifRange) {
|
|
382
|
+
rangeOk = ifRange.startsWith('"') || ifRange.startsWith('W/')
|
|
383
|
+
? ifRange === etag
|
|
384
|
+
: Date.parse(ifRange) === Math.floor(mtimeMs / 1000) * 1000;
|
|
385
|
+
}
|
|
386
|
+
// Range request (skip when forcing a status, e.g. SPA fallback, or If-Range miss).
|
|
387
|
+
const range = forceStatus || !rangeOk ? null : parseRange(req.headers.range, size);
|
|
388
|
+
if (range === 'invalid') {
|
|
389
|
+
res.writeHead(416, { ...baseHeaders, 'Content-Range': `bytes */${size}` });
|
|
390
|
+
res.end();
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
if (range) {
|
|
394
|
+
const [start, end] = range;
|
|
395
|
+
res.writeHead(206, {
|
|
396
|
+
...baseHeaders,
|
|
397
|
+
'Content-Range': `bytes ${start}-${end}/${size}`,
|
|
398
|
+
'Content-Length': end - start + 1,
|
|
399
|
+
});
|
|
400
|
+
if (method === 'HEAD') {
|
|
401
|
+
res.end();
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
pipeFile(res, filePath, start, end);
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
res.writeHead(forceStatus ?? 200, { ...baseHeaders, 'Content-Length': size });
|
|
408
|
+
if (method === 'HEAD') {
|
|
409
|
+
res.end();
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
pipeFile(res, filePath);
|
|
413
|
+
}
|
|
414
|
+
function pipeFile(res, filePath, start, end) {
|
|
415
|
+
const stream = start !== undefined && end !== undefined
|
|
416
|
+
? createReadStream(filePath, { start, end })
|
|
417
|
+
: createReadStream(filePath);
|
|
418
|
+
stream.on('error', () => {
|
|
419
|
+
// Headers are already sent by the time we stream, so we can only abort.
|
|
420
|
+
res.destroy();
|
|
421
|
+
});
|
|
422
|
+
res.on('close', () => stream.destroy());
|
|
423
|
+
stream.pipe(res);
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Create (but do not start) a static HTTP server for `options.root`.
|
|
427
|
+
* Call `.listen()` yourself, or use {@link startStaticServer} to listen and get
|
|
428
|
+
* a resolved {@link StaticServerHandle}.
|
|
429
|
+
*/
|
|
430
|
+
export function createStaticServer(options) {
|
|
431
|
+
return createServer(createStaticHandler(options));
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Start a static server and resolve once it's listening. When `port` is omitted
|
|
435
|
+
* or `0`, the OS assigns a free port and the resolved handle reports it.
|
|
436
|
+
*/
|
|
437
|
+
export function startStaticServer(options) {
|
|
438
|
+
const host = options.host ?? '127.0.0.1';
|
|
439
|
+
const port = options.port ?? 0;
|
|
440
|
+
const server = createStaticServer(options);
|
|
441
|
+
return new Promise((resolvePromise, reject) => {
|
|
442
|
+
const onError = (err) => {
|
|
443
|
+
server.removeListener('listening', onListening);
|
|
444
|
+
reject(err);
|
|
445
|
+
};
|
|
446
|
+
const onListening = () => {
|
|
447
|
+
server.removeListener('error', onError);
|
|
448
|
+
const addr = server.address();
|
|
449
|
+
const boundPort = addr.port;
|
|
450
|
+
const displayHost = host === '0.0.0.0' || host === '::' ? 'localhost' : host;
|
|
451
|
+
resolvePromise({
|
|
452
|
+
port: boundPort,
|
|
453
|
+
host,
|
|
454
|
+
url: `http://${displayHost}:${boundPort}`,
|
|
455
|
+
server,
|
|
456
|
+
close: () => new Promise((res, rej) => {
|
|
457
|
+
server.close(err => (err ? rej(err) : res()));
|
|
458
|
+
}),
|
|
459
|
+
});
|
|
460
|
+
};
|
|
461
|
+
server.once('error', onError);
|
|
462
|
+
server.listen(port, host, onListening);
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
//# sourceMappingURL=static.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"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"}
|