st 1.2.2 → 2.0.0
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/.travis.yml +11 -2
- package/README.md +28 -22
- package/bin/server.js +75 -66
- package/package.json +12 -10
- package/st.js +505 -449
- package/test/basic.js +133 -0
- package/test/cli/basic-test.js +32 -0
- package/test/cli/common.js +108 -0
- package/test/cli/host-test.js +92 -0
- package/test/common.js +66 -0
- package/test/cors.js +19 -0
- package/test/dot-common.js +44 -0
- package/test/dot-false.js +19 -0
- package/test/dot-true.js +20 -0
- package/test/explicit-cache-control.js +12 -0
- package/test/fd-limit.js +10 -0
- package/test/fixtures/.dotted-dir/.index.html +11 -0
- package/test/fixtures/.dotted-dir/index.html +11 -0
- package/test/fixtures/index.html +11 -0
- package/test/fixtures/space in filename.txt +1 -0
- package/test/gzip-after-no-gzip.js +38 -0
- package/test/middleware.js +17 -0
- package/test/multi-mount.js +251 -0
- package/test/no-cache.js +19 -0
- package/test/no-content-maxage.js +10 -0
- package/test/no-cors.js +14 -0
- package/test/no-fd-cache.js +8 -0
- package/test/no-gzip-accepted-no-cache.js +32 -0
- package/test/no-gzip-accepted.js +31 -0
- package/test/no-gzip.js +18 -0
- package/test/parent-path.js +8 -0
- package/test/passthrough.js +75 -0
- package/test/preset-cache-control.js +65 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
const st = require('../st.js')
|
|
2
|
+
const test = require('tap').test
|
|
3
|
+
const port = process.env.PORT || 1337
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const request = require('request')
|
|
6
|
+
const assert = require('assert')
|
|
7
|
+
const fs = require('fs')
|
|
8
|
+
const http = require('http')
|
|
9
|
+
|
|
10
|
+
let middlewareServer
|
|
11
|
+
let server
|
|
12
|
+
|
|
13
|
+
// mount the dirname on the /test url
|
|
14
|
+
const mount1 = st({
|
|
15
|
+
autoindex: true,
|
|
16
|
+
path: path.dirname(__dirname),
|
|
17
|
+
url: '/test',
|
|
18
|
+
cache: {
|
|
19
|
+
fd: {
|
|
20
|
+
max: 3
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
// mount the test dir on the /blerg url
|
|
26
|
+
const mount2 = st({
|
|
27
|
+
autoindex: true,
|
|
28
|
+
path: __dirname,
|
|
29
|
+
url: '/blerg',
|
|
30
|
+
cache: {
|
|
31
|
+
fd: {
|
|
32
|
+
max: 3
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
function req (url, headers, cb) {
|
|
38
|
+
if (typeof headers === 'function') {
|
|
39
|
+
cb = headers
|
|
40
|
+
headers = {}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let reqs = 0
|
|
44
|
+
let errState = null
|
|
45
|
+
let prev = null
|
|
46
|
+
|
|
47
|
+
request({
|
|
48
|
+
encoding: null,
|
|
49
|
+
url: `http://localhost:${port}${url}`,
|
|
50
|
+
headers: headers,
|
|
51
|
+
agentOptions: { maxSockets: 50 }
|
|
52
|
+
}, next)
|
|
53
|
+
request({
|
|
54
|
+
encoding: null,
|
|
55
|
+
url: `http://localhost:${(port + 1)}${url}`,
|
|
56
|
+
headers: headers,
|
|
57
|
+
agentOptions: { maxSockets: 50 }
|
|
58
|
+
}, next)
|
|
59
|
+
|
|
60
|
+
function next (er, res, body) {
|
|
61
|
+
if (errState) {
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
if (er) {
|
|
65
|
+
errState = er
|
|
66
|
+
return cb(er, res, body)
|
|
67
|
+
}
|
|
68
|
+
if (++reqs === 2) {
|
|
69
|
+
assert.strictEqual(res.statusCode, prev.res.statusCode)
|
|
70
|
+
// compare dates, they should be approximately the same
|
|
71
|
+
assert(Math.abs(new Date(res.headers.date).getTime() -
|
|
72
|
+
new Date(res.headers.date).getTime()) < 1000)
|
|
73
|
+
// compare the headers minus the 'date' value
|
|
74
|
+
res.headers.date = prev.res.headers.date = null
|
|
75
|
+
assert.deepStrictEqual(res.headers, prev.res.headers)
|
|
76
|
+
assert.strictEqual(`${body}`, `${prev.body}`)
|
|
77
|
+
return cb(er, res, body)
|
|
78
|
+
}
|
|
79
|
+
prev = { res: res, body: body }
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
test('setup middleware server', function (t) {
|
|
84
|
+
// using the middleware approach
|
|
85
|
+
middlewareServer = http.createServer(function (req, res) {
|
|
86
|
+
mount1(req, res, function () {
|
|
87
|
+
mount2(req, res, function () {
|
|
88
|
+
res.statusCode = 404
|
|
89
|
+
return res.end(`Not a match: ${req.url}`)
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
})
|
|
93
|
+
middlewareServer.listen(port, '127.0.0.1', function () {
|
|
94
|
+
t.pass('listening')
|
|
95
|
+
t.end()
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test('setup regular server', function (t) {
|
|
100
|
+
server = http.createServer(function (req, res) {
|
|
101
|
+
if (!mount1(req, res) && !mount2(req, res)) {
|
|
102
|
+
res.statusCode = 404
|
|
103
|
+
return res.end(`Not a match: ${req.url}`)
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
server.listen(port + 1, '127.0.0.1', function () {
|
|
107
|
+
t.pass('listening')
|
|
108
|
+
t.end()
|
|
109
|
+
})
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
let stEtag
|
|
113
|
+
const stExpect = fs.readFileSync(require.resolve('../st.js')).toString()
|
|
114
|
+
|
|
115
|
+
test('/test/st.js', function (t) {
|
|
116
|
+
req('/test/st.js', function (er, res, body) {
|
|
117
|
+
t.equal(res.statusCode, 200)
|
|
118
|
+
t.ok(res.headers.etag)
|
|
119
|
+
stEtag = res.headers.etag
|
|
120
|
+
t.equal(body.toString(), stExpect)
|
|
121
|
+
t.end()
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
test('/test/st.js 304', function (t) {
|
|
126
|
+
req('/test/st.js', { 'if-none-match': stEtag }, function (er, res, body) {
|
|
127
|
+
t.equal(res.statusCode, 304)
|
|
128
|
+
t.equal(body.length, 0)
|
|
129
|
+
t.end()
|
|
130
|
+
})
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
let mmEtag
|
|
134
|
+
const mmExpect = fs.readFileSync(__filename, 'utf8')
|
|
135
|
+
test('/blerg/multi-mount.js', function (t) {
|
|
136
|
+
req('/blerg/multi-mount.js', function (er, res, body) {
|
|
137
|
+
t.equal(res.statusCode, 200)
|
|
138
|
+
t.ok(res.headers.etag)
|
|
139
|
+
mmEtag = res.headers.etag
|
|
140
|
+
t.equal(body.toString(), mmExpect)
|
|
141
|
+
t.end()
|
|
142
|
+
})
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
test('/test/test/multi-mount.js', function (t) {
|
|
146
|
+
req('/test/test/multi-mount.js', function (er, res, body) {
|
|
147
|
+
t.equal(res.statusCode, 200)
|
|
148
|
+
t.equal(mmEtag, res.headers.etag)
|
|
149
|
+
t.equal(body.toString(), mmExpect)
|
|
150
|
+
t.end()
|
|
151
|
+
})
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
let rmEtag
|
|
155
|
+
const rmExpect = fs.readFileSync(path.resolve(__dirname, '../README.md'), 'utf8')
|
|
156
|
+
let pjEtag
|
|
157
|
+
const pjExpect = fs.readFileSync(path.resolve(__dirname, '../package.json'), 'utf8')
|
|
158
|
+
let idEtag
|
|
159
|
+
const idExpect = fs.readFileSync(path.join(__dirname, '/fixtures/index.html'), 'utf8')
|
|
160
|
+
test('just get a few more etags', function (t) {
|
|
161
|
+
let n = 3
|
|
162
|
+
|
|
163
|
+
req('/test/package.json', function (er, res, body) {
|
|
164
|
+
if (er) {
|
|
165
|
+
throw er
|
|
166
|
+
}
|
|
167
|
+
t.equal(body.toString(), pjExpect)
|
|
168
|
+
pjEtag = res.headers.etag
|
|
169
|
+
if (--n === 0) {
|
|
170
|
+
t.end()
|
|
171
|
+
}
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
req('/test/README.md', function (er, res, body) {
|
|
175
|
+
if (er) {
|
|
176
|
+
throw er
|
|
177
|
+
}
|
|
178
|
+
t.equal(body.toString(), rmExpect)
|
|
179
|
+
rmEtag = res.headers.etag
|
|
180
|
+
if (--n === 0) {
|
|
181
|
+
t.end()
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
req('/test/test/fixtures/index.html', function (er, res, body) {
|
|
186
|
+
if (er) {
|
|
187
|
+
throw er
|
|
188
|
+
}
|
|
189
|
+
t.equal(body.toString(), idExpect)
|
|
190
|
+
idEtag = res.headers.etag
|
|
191
|
+
if (--n === 0) {
|
|
192
|
+
t.end()
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
test('many parallel requests', function (t) {
|
|
198
|
+
const n = 50
|
|
199
|
+
const reqs =
|
|
200
|
+
[['/test/test/multi-mount.js', mmEtag, mmExpect],
|
|
201
|
+
['/blerg/multi-mount.js', mmEtag, mmExpect],
|
|
202
|
+
['/test/st.js', stEtag, stExpect],
|
|
203
|
+
['/test/README.md', rmEtag, rmExpect],
|
|
204
|
+
['/test/package.json', pjEtag, pjExpect],
|
|
205
|
+
['/test/test/fixtures/index.html', idEtag, idExpect],
|
|
206
|
+
['/blerg/fixtures/index.html', idEtag, idExpect]]
|
|
207
|
+
|
|
208
|
+
let total = n * reqs.length
|
|
209
|
+
|
|
210
|
+
for (let i = 0; i < n; i++) {
|
|
211
|
+
reqs.forEach(function (r) {
|
|
212
|
+
req(r[0], next(r))
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function next (r) {
|
|
217
|
+
return (er, res, body) => {
|
|
218
|
+
if (er) {
|
|
219
|
+
console.error('problem with', r[0])
|
|
220
|
+
throw er
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
t.pass(r[0])
|
|
224
|
+
t.ok(res)
|
|
225
|
+
t.ok(res.headers)
|
|
226
|
+
t.equal(res.headers.etag, r[1])
|
|
227
|
+
t.equal(body.toString(), r[2].toString())
|
|
228
|
+
|
|
229
|
+
if (--total === 0) {
|
|
230
|
+
process.nextTick(() => {
|
|
231
|
+
t.ok(require('fd')._totalOpenFds <= 6) // max of 3 fds per mount
|
|
232
|
+
t.end()
|
|
233
|
+
})
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
test('shutdown regular server', (t) => {
|
|
240
|
+
server.close(() => {
|
|
241
|
+
t.pass('closed')
|
|
242
|
+
t.end()
|
|
243
|
+
})
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
test('shutdown middleware server', (t) => {
|
|
247
|
+
middlewareServer.close(() => {
|
|
248
|
+
t.pass('closed')
|
|
249
|
+
t.end()
|
|
250
|
+
})
|
|
251
|
+
})
|
package/test/no-cache.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// turn off ALL caching.
|
|
2
|
+
global.options = {
|
|
3
|
+
cache: false
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// otherwise just the same as basic.
|
|
7
|
+
const { mount } = require('./basic.js')
|
|
8
|
+
const { test } = require('tap')
|
|
9
|
+
|
|
10
|
+
// additional tests to ensure that it's actually not caching.
|
|
11
|
+
|
|
12
|
+
test('all caches should be empty', (t) => {
|
|
13
|
+
t.same(mount._this.cache.fd._cache.dump(), [])
|
|
14
|
+
t.same(mount._this.cache.stat._cache.dump(), [])
|
|
15
|
+
t.same(mount._this.cache.index._cache.dump(), [])
|
|
16
|
+
t.same(mount._this.cache.readdir._cache.dump(), [])
|
|
17
|
+
t.same(mount._this.cache.content._cache.dump(), [])
|
|
18
|
+
t.end()
|
|
19
|
+
})
|
package/test/no-cors.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
global.options = {
|
|
2
|
+
cors: false
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
const { req } = require('./common')
|
|
6
|
+
const test = require('tap').test
|
|
7
|
+
|
|
8
|
+
test('without CORS headers', function (t) {
|
|
9
|
+
req('/test/st.js', function (er, res) {
|
|
10
|
+
t.error(er)
|
|
11
|
+
t.notOk(res.headers['access-control-allow-origin'])
|
|
12
|
+
t.end()
|
|
13
|
+
})
|
|
14
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
global.options = {
|
|
2
|
+
cache: false // cache invokes a separate path
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
const fs = require('fs')
|
|
6
|
+
const path = require('path')
|
|
7
|
+
const crypto = require('crypto')
|
|
8
|
+
const rimraf = require('rimraf')
|
|
9
|
+
const { test } = require('tap')
|
|
10
|
+
const { req } = require('./common.js')
|
|
11
|
+
const testFileName = 'no-gzip-accepted-no-cache.testfile'
|
|
12
|
+
const testFile = path.join(__dirname, '../', testFileName)
|
|
13
|
+
|
|
14
|
+
const rndData = crypto.randomBytes(1024 * 128).toString('hex') // significantly larger than highWaterMark
|
|
15
|
+
|
|
16
|
+
test('does not gzip the response', (t) => {
|
|
17
|
+
t.on('end', () => {
|
|
18
|
+
rimraf(testFile, () => {})
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
fs.writeFile(testFile, rndData, (err) => {
|
|
22
|
+
t.error(err)
|
|
23
|
+
|
|
24
|
+
req(`/test/${testFileName}`, { 'accept-encoding': 'none' }, (er, res, body) => {
|
|
25
|
+
t.error(er)
|
|
26
|
+
t.equal(res.statusCode, 200)
|
|
27
|
+
t.notOk(res.headers['content-encoding'])
|
|
28
|
+
t.equal(body.toString(), rndData)
|
|
29
|
+
t.end()
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
global.options = {
|
|
2
|
+
}
|
|
3
|
+
|
|
4
|
+
const fs = require('fs')
|
|
5
|
+
const path = require('path')
|
|
6
|
+
const crypto = require('crypto')
|
|
7
|
+
const rimraf = require('rimraf')
|
|
8
|
+
const { test } = require('tap')
|
|
9
|
+
const { req } = require('./common.js')
|
|
10
|
+
const testFileName = 'no-gzip-accepted.testfile'
|
|
11
|
+
const testFile = path.join(__dirname, '../', testFileName)
|
|
12
|
+
|
|
13
|
+
const rndData = crypto.randomBytes(1024 * 128).toString('hex') // significantly larger than highWaterMark
|
|
14
|
+
|
|
15
|
+
test('does not gzip the response', (t) => {
|
|
16
|
+
t.on('end', () => {
|
|
17
|
+
rimraf(testFile, () => {})
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
fs.writeFile(testFile, rndData, (err) => {
|
|
21
|
+
t.error(err)
|
|
22
|
+
|
|
23
|
+
req('/test/' + testFileName, { 'accept-encoding': 'none' }, (er, res, body) => {
|
|
24
|
+
t.error(er)
|
|
25
|
+
t.equal(res.statusCode, 200)
|
|
26
|
+
t.notOk(res.headers['content-encoding'])
|
|
27
|
+
t.equal(body.toString(), rndData)
|
|
28
|
+
t.end()
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
})
|
package/test/no-gzip.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// turn off gzip compression
|
|
2
|
+
global.options = {
|
|
3
|
+
gzip: false
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const { test } = require('tap')
|
|
7
|
+
const { req, stExpect } = require('./basic.js')
|
|
8
|
+
|
|
9
|
+
// additional test to ensure that it's actually not gzipping
|
|
10
|
+
|
|
11
|
+
test('does not gzip the response', (t) => {
|
|
12
|
+
req('/test/st.js', { 'accept-encoding': 'gzip' }, (er, res, body) => {
|
|
13
|
+
t.equal(res.statusCode, 200)
|
|
14
|
+
t.notOk(res.headers['content-encoding'])
|
|
15
|
+
t.equal(body.toString(), stExpect)
|
|
16
|
+
t.end()
|
|
17
|
+
})
|
|
18
|
+
})
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const { test } = require('tap')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const st = require('../st.js')
|
|
4
|
+
|
|
5
|
+
const opts = Object.assign({
|
|
6
|
+
index: false,
|
|
7
|
+
path: path.resolve(__dirname, './fixtures'),
|
|
8
|
+
url: '/',
|
|
9
|
+
passthrough: true
|
|
10
|
+
}, global.options || {})
|
|
11
|
+
|
|
12
|
+
const mount = st(opts)
|
|
13
|
+
|
|
14
|
+
test('call next() if passthrough is set', (t) => {
|
|
15
|
+
const req = { method: 'GET', url: '/doesnotexist.txt', headers: {} }
|
|
16
|
+
const res = {
|
|
17
|
+
error: () => t.end(),
|
|
18
|
+
setHeader: () => {},
|
|
19
|
+
end: () => {}
|
|
20
|
+
}
|
|
21
|
+
t.plan(2)
|
|
22
|
+
mount(req, res, () => {
|
|
23
|
+
t.ok(true, 'next called with nonexistant file')
|
|
24
|
+
req.url = '/'
|
|
25
|
+
mount(req, res, () => {
|
|
26
|
+
t.ok(true, 'next called without indexing')
|
|
27
|
+
t.end()
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const opts2 = Object.assign({
|
|
33
|
+
autoindex: true,
|
|
34
|
+
path: path.resolve(__dirname, './fixtures'),
|
|
35
|
+
url: '/'
|
|
36
|
+
}, global.options || {})
|
|
37
|
+
const mount2 = st(opts2)
|
|
38
|
+
|
|
39
|
+
test('return error if passthrough is not set', (t) => {
|
|
40
|
+
const req = { method: 'GET', url: '/doesnotexist.txt', headers: {} }
|
|
41
|
+
const res = {
|
|
42
|
+
setHeader: () => {},
|
|
43
|
+
error: () => {
|
|
44
|
+
t.ok(true, 'error used')
|
|
45
|
+
t.end()
|
|
46
|
+
},
|
|
47
|
+
end: () => {}
|
|
48
|
+
}
|
|
49
|
+
t.plan(1)
|
|
50
|
+
mount2(req, res, () => {
|
|
51
|
+
t.end()
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('does not set headers if passthrough is set', (t) => {
|
|
56
|
+
const req = { method: 'GET', url: '/doesnotexist.txt', headers: {} }
|
|
57
|
+
const res = {
|
|
58
|
+
error: () => t.end(),
|
|
59
|
+
_headers: [],
|
|
60
|
+
setHeader: (header) => {
|
|
61
|
+
res._headers.push(header)
|
|
62
|
+
},
|
|
63
|
+
end: () => {}
|
|
64
|
+
}
|
|
65
|
+
t.plan(2)
|
|
66
|
+
mount(req, res, () => {
|
|
67
|
+
t.notOk(res._headers.length, 'headers are not set on a non-existant file')
|
|
68
|
+
req.url = '/'
|
|
69
|
+
|
|
70
|
+
mount(req, res, () => {
|
|
71
|
+
t.notOk(res._headers.length, 'headers are not set with no index')
|
|
72
|
+
t.end()
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
})
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const st = require('../st.js')
|
|
2
|
+
const { test, tearDown } = require('tap')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
const http = require('http')
|
|
5
|
+
const request = require('request')
|
|
6
|
+
const port = process.env.PORT || 1337
|
|
7
|
+
|
|
8
|
+
const opts = Object.assign({
|
|
9
|
+
index: false,
|
|
10
|
+
path: path.dirname(__dirname),
|
|
11
|
+
url: '/test'
|
|
12
|
+
}, global.options || {})
|
|
13
|
+
|
|
14
|
+
const mount = st(opts)
|
|
15
|
+
let server
|
|
16
|
+
let cacheControl = null
|
|
17
|
+
|
|
18
|
+
function req (url, headers, cb) {
|
|
19
|
+
if (typeof headers === 'function') {
|
|
20
|
+
cb = headers
|
|
21
|
+
headers = {}
|
|
22
|
+
}
|
|
23
|
+
request({
|
|
24
|
+
encoding: null,
|
|
25
|
+
url: 'http://localhost:' + port + url,
|
|
26
|
+
headers: headers
|
|
27
|
+
}, cb)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
test('setup', (t) => {
|
|
31
|
+
server = http.createServer((req, res) => {
|
|
32
|
+
if (cacheControl) {
|
|
33
|
+
res.setHeader('cache-control', cacheControl)
|
|
34
|
+
}
|
|
35
|
+
if (!mount(req, res)) {
|
|
36
|
+
res.statusCode = 404
|
|
37
|
+
return res.end('Not a match: ' + req.url)
|
|
38
|
+
}
|
|
39
|
+
}).listen(port, () => {
|
|
40
|
+
t.pass('listening')
|
|
41
|
+
t.end()
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
tearDown(() => {
|
|
46
|
+
server.close()
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
test('simple request', (t) => {
|
|
50
|
+
cacheControl = null
|
|
51
|
+
req('/test/st.js', (er, res, body) => {
|
|
52
|
+
t.error(er)
|
|
53
|
+
t.equal(res.headers['cache-control'], 'public, max-age=600')
|
|
54
|
+
t.end()
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('pre-set cache-control', (t) => {
|
|
59
|
+
cacheControl = 'I\'m so excited, and I just can\'t hide it'
|
|
60
|
+
req('/test/st.js', (er, res, body) => {
|
|
61
|
+
t.error(er)
|
|
62
|
+
t.equal(res.headers['cache-control'], cacheControl)
|
|
63
|
+
t.end()
|
|
64
|
+
})
|
|
65
|
+
})
|