-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.ts
More file actions
executable file
·92 lines (80 loc) · 2.64 KB
/
main.ts
File metadata and controls
executable file
·92 lines (80 loc) · 2.64 KB
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import { assert } from '@std/assert';
import { parseArgs } from '@std/cli/parse-args';
import { default as config } from './deno.json' with { type: 'json' };
const { name, version } = config;
const args = parseArgs(Deno.args, {
alias: {
h: 'help',
p: 'port',
v: 'version',
},
boolean: ['help', 'version'],
default: {
help: false,
hostname: 'localhost',
port: '8080',
version: false,
},
string: ['hostname', 'port'],
});
if (args.version) {
console.log(`${name} ${version}
using deno ${Deno.version.deno}`);
Deno.exit();
}
if (args.help) {
console.log(`Serve static files over HTTP
Usage: deno ./main.ts [options] [path]
Options
-h, --help Show this help message and exit
-p, --port Port to listen on (default: 8080)
--hostname Hostname to listen on (default: localhost)`);
Deno.exit();
}
const { hostname, port } = args;
const ROOT = `${args._[0] ?? './static'}`;
const allowNet = await Deno.permissions.request({ name: 'net', host: `${hostname}:${port}` });
assert(allowNet.state === 'granted', 'Network permission is required');
const allowRead = await Deno.permissions.request({ name: 'read', path: ROOT });
assert(allowRead.state === 'granted', 'Read permission is required');
function getFilePath(req: Request): string {
const url = new URL(req.url);
let filepath = decodeURIComponent(url.pathname.slice(1)) || 'index.html';
if (filepath.endsWith('/')) {
filepath += 'index.html';
}
return `${ROOT}/${filepath}`;
}
function redirectDirectory(req: Request): Response {
return new Response('', {
status: 302,
headers: { Location: `${new URL(req.url).pathname}/` },
});
}
async function handleRequest(req: Request): Promise<Response> {
try {
const file = await Deno.open(getFilePath(req), { read: true });
if ((await file.stat()).isDirectory) {
return redirectDirectory(req);
}
return new Response(file.readable);
} catch (error) {
const status = error instanceof Deno.errors.NotFound || Deno.errors.NotADirectory ? 404 : 500;
return new Response('', { status });
}
}
function log(req: Request, res: Response): void {
console.log(`[${new Date().toLocaleTimeString()}] ${getFilePath(req).slice(ROOT.length)} - ${res.status}`);
}
Deno.serve(
{
hostname,
port: Number.parseInt(port),
onListen: () => console.log(`\nServing "${ROOT}" folder on http://${hostname}:${port}\n`),
},
async (req: Request) => {
const res = await handleRequest(req);
log(req, res);
return res;
}
);