/
sirv-cli.js
167 lines (132 loc) · 4.69 KB
/
sirv-cli.js
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import { suite } from 'uvu';
import assert from 'uvu/assert';
import selfsigned from 'selfsigned';
import * as utils from './helpers';
const help = suite('help');
help('--help', () => {
let pid = utils.exec('--help');
assert.is(pid.status, 0);
assert.snapshot(
// prints extra NL; dedent doesnt cooperate
pid.stdout.toString().trimRight() + '\n ',
`
Description
Run a static file server
Usage
$ sirv [dir] [options]
Options
-D, --dev Enable "dev" mode
-e, --etag Enable "ETag" header
-d, --dotfiles Enable dotfile asset requests
-c, --cors Enable "CORS" headers to allow any origin requestor
-G, --gzip Send precompiled "*.gz" files when "gzip" is supported (default true)
-B, --brotli Send precompiled "*.br" files when "brotli" is supported (default true)
-m, --maxage Enable "Cache-Control" header & define its "max-age" value (sec)
-i, --immutable Enable the "immutable" directive for "Cache-Control" header
-k, --http2 Enable the HTTP/2 protocol. Requires Node.js 8.4.0+
-C, --cert Path to certificate file for HTTP/2 server
-K, --key Path to certificate key for HTTP/2 server
-P, --pass Passphrase to decrypt a certificate key
-s, --single Serve as single-page application with "index.html" fallback
-I, --ignores Any URL pattern(s) to ignore "index.html" assumptions
-q, --quiet Disable logging to terminal
-H, --host Hostname to bind (default localhost)
-p, --port Port to bind (default 8080)
-v, --version Displays current version
-h, --help Displays this message
Examples
$ sirv build --cors --port 8888
$ sirv public --quiet --etag --maxage 31536000 --immutable
$ sirv public --http2 --key priv.pem --cert cert.pem
$ sirv public -qeim 31536000
$ sirv --port 8888 --etag
$ sirv --host --dev
`
);
});
help.run();
// ---
const basic = suite('basic');
basic('should start a server', async () => {
let server = await utils.spawn();
try {
let res = await server.send('GET', '/');
await utils.matches(res, 200, 'index.html', 'utf8');
} finally {
await server.close();
}
});
basic.run();
// ---
const cors = suite('cors');
cors('should attach CORS headers to response', async () => {
let server = await utils.spawn('--cors');
try {
let res = await server.send('GET', '/blog');
await utils.matches(res, 200, 'blog.html', 'utf8');
assert.is(res.headers['access-control-allow-origin'], '*');
assert.is(res.headers['access-control-allow-headers'], 'Origin, Content-Type, Accept, Range');
} finally {
await server.close();
}
});
cors.run();
// ---
const port = suite('port');
port('should customize port via flag', async () => {
let server = await utils.spawn('--port', '8080');
try {
assert.is(server.address.hostname, 'localhost');
assert.is(server.address.port, '8080');
} finally {
await server.close();
}
});
port.run();
// ---
const host = suite('host');
host('should expose to network via empty host flag', async () => {
let server = await utils.spawn('--host');
try {
assert.is(server.address.hostname, '0.0.0.0');
} finally {
await server.close();
}
});
host.run();
// ---
const http2 = suite('http2');
http2('requires "key" path argument', async () => {
let pid = await utils.exec('--http2');
assert.ok(pid.stderr.toString().includes(`HTTP/2 requires "key" and "cert" values`));
assert.is(pid.status, 1);
});
http2('requires "cert" path argument', async () => {
let pid = await utils.exec('--http2', '--key', 'foo');
assert.ok(pid.stderr.toString().includes(`HTTP/2 requires "key" and "cert" values`));
assert.is(pid.status, 1);
});
http2('should start a HTTP/2 server with valid args', async () => {
let pems = selfsigned.generate();
let key = await utils.write('foobar.key', pems.private);
let cert = await utils.write('foobar.cert', pems.cert);
let server = await utils.spawn('--http2', '--key', key, '--cert', cert);
try {
assert.is(server.address.protocol, 'https:');
} finally {
await server.close();
}
});
http2('should have backward compatibility with HTTP/1', async () => {
let pems = selfsigned.generate();
let key = await utils.write('foobar.key2', pems.private);
let cert = await utils.write('foobar.cert2', pems.cert);
let server = await utils.spawn('--http2', '--key', key, '--cert', cert);
try {
let res = await server.send('GET', '/blog', { rejectUnauthorized: false });
await utils.matches(res, 200, 'blog.html', 'utf8');
} finally {
await server.close();
}
});
http2.run();