@superhero/http-server 4.4.7 → 4.7.1
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 +5 -5
- package/conditions/upstream/header/accept.js +13 -0
- package/conditions/upstream/header/content-type.js +13 -0
- package/conditions/upstream/method.js +7 -0
- package/index.js +9 -9
- package/index.test.js +56 -57
- package/package.json +14 -11
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ const settings = {
|
|
|
67
67
|
router: {
|
|
68
68
|
routes: {
|
|
69
69
|
hello: {
|
|
70
|
-
|
|
70
|
+
condition: '/hello',
|
|
71
71
|
dispatcher: 'hello-dispatcher',
|
|
72
72
|
},
|
|
73
73
|
},
|
|
@@ -115,7 +115,7 @@ const serverSettings = {
|
|
|
115
115
|
router: {
|
|
116
116
|
routes: {
|
|
117
117
|
secure: {
|
|
118
|
-
|
|
118
|
+
condition: '/secure',
|
|
119
119
|
dispatcher: 'secure-dispatcher',
|
|
120
120
|
},
|
|
121
121
|
},
|
|
@@ -145,7 +145,7 @@ const settings = {
|
|
|
145
145
|
router: {
|
|
146
146
|
routes: {
|
|
147
147
|
custom: {
|
|
148
|
-
|
|
148
|
+
condition: '/custom',
|
|
149
149
|
dispatcher: 'custom-dispatcher',
|
|
150
150
|
},
|
|
151
151
|
},
|
|
@@ -174,7 +174,7 @@ const settings = {
|
|
|
174
174
|
router: {
|
|
175
175
|
routes: {
|
|
176
176
|
abort: {
|
|
177
|
-
|
|
177
|
+
condition: '/abort',
|
|
178
178
|
dispatcher: 'abort-dispatcher',
|
|
179
179
|
},
|
|
180
180
|
},
|
|
@@ -208,7 +208,7 @@ const settings = {
|
|
|
208
208
|
router: {
|
|
209
209
|
routes: {
|
|
210
210
|
sse: {
|
|
211
|
-
|
|
211
|
+
condition: '/sse',
|
|
212
212
|
dispatcher: 'sse-dispatcher',
|
|
213
213
|
},
|
|
214
214
|
},
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export default
|
|
2
|
+
{
|
|
3
|
+
isValid(request, session)
|
|
4
|
+
{
|
|
5
|
+
const
|
|
6
|
+
header = request.headers['accept'],
|
|
7
|
+
lowerCased = header.toLowerCase(),
|
|
8
|
+
accept = lowerCased.split(';')[0].split('*')[0].trim()
|
|
9
|
+
|
|
10
|
+
return [session.route['condition.accept']].flat().some(supported =>
|
|
11
|
+
supported.startsWith(accept) || accept.startsWith(supported.split('*')[0]))
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export default
|
|
2
|
+
{
|
|
3
|
+
isValid(request, session)
|
|
4
|
+
{
|
|
5
|
+
const
|
|
6
|
+
header = request.headers['content-type'],
|
|
7
|
+
lowerCased = header.toLowerCase(),
|
|
8
|
+
contentType = lowerCased.split(';')[0].split('*')[0].trim()
|
|
9
|
+
|
|
10
|
+
return [session.route['condition.content-type']].flat().some(supported =>
|
|
11
|
+
supported.startsWith(contentType) || contentType.startsWith(supported.split('*')[0]))
|
|
12
|
+
}
|
|
13
|
+
}
|
package/index.js
CHANGED
|
@@ -231,17 +231,17 @@ export default class HttpServer
|
|
|
231
231
|
this.log.info`${requestID} ⇡ request`
|
|
232
232
|
|
|
233
233
|
const
|
|
234
|
-
session
|
|
235
|
-
request
|
|
236
|
-
url
|
|
237
|
-
|
|
238
|
-
body
|
|
239
|
-
abortion
|
|
234
|
+
session = {},
|
|
235
|
+
request = {},
|
|
236
|
+
url = new URL(upstream.url, `${protocol}://${upstream.headers.host}`),
|
|
237
|
+
condition = url.pathname.replace(/\/+$/, ''), // removed trailing slashes
|
|
238
|
+
body = this.#bufferBody(upstream, request),
|
|
239
|
+
abortion = new AbortController
|
|
240
240
|
|
|
241
241
|
Object.defineProperties(request,
|
|
242
242
|
{
|
|
243
|
-
// configurable and writable
|
|
244
|
-
|
|
243
|
+
// configurable and writable condition property
|
|
244
|
+
condition : { writable:true, configurable:true, value:condition },
|
|
245
245
|
// configurable and writable stream data reader
|
|
246
246
|
body : { writable:true, configurable:true, value:body },
|
|
247
247
|
// enumerable data readers, non-configurable
|
|
@@ -254,7 +254,7 @@ export default class HttpServer
|
|
|
254
254
|
// non enumerable and non-configurable session properties
|
|
255
255
|
downstream : { value:downstream },
|
|
256
256
|
upstream : { value:upstream },
|
|
257
|
-
abortion : { value:abortion }
|
|
257
|
+
abortion : { value:abortion },
|
|
258
258
|
})
|
|
259
259
|
|
|
260
260
|
Object.defineProperty(session, 'view', { enumerable: true, value: new View(session) })
|
package/index.test.js
CHANGED
|
@@ -135,14 +135,14 @@ suite('@superhero/http-server', () =>
|
|
|
135
135
|
|
|
136
136
|
test('Support connection keep-alive header', async () =>
|
|
137
137
|
{
|
|
138
|
+
locator.set('foo-dispatcher', { dispatch: () => null })
|
|
139
|
+
|
|
138
140
|
server.router.setRoutes(
|
|
139
141
|
{ 'foo':
|
|
140
|
-
{
|
|
142
|
+
{ condition : '/test/foo',
|
|
141
143
|
dispatcher : 'foo-dispatcher'
|
|
142
144
|
}})
|
|
143
145
|
|
|
144
|
-
locator.set('foo-dispatcher', { dispatch: () => null })
|
|
145
|
-
|
|
146
146
|
// Set the keep-alive timeout to 10 seconds on the server.
|
|
147
147
|
const keepAlive = 10
|
|
148
148
|
server.http1Server.keepAliveTimeout = keepAlive * 1e3
|
|
@@ -172,19 +172,19 @@ suite('@superhero/http-server', () =>
|
|
|
172
172
|
{
|
|
173
173
|
test('Can dispatch a request aligned to the route map', async () =>
|
|
174
174
|
{
|
|
175
|
+
let dispatched
|
|
176
|
+
locator.set('foo-dispatcher', { dispatch: () => dispatched = 'foo' })
|
|
177
|
+
locator.set('bar-dispatcher', { dispatch: () => dispatched = 'bar' })
|
|
178
|
+
|
|
175
179
|
server.router.setRoutes(
|
|
176
180
|
{ 'foo':
|
|
177
|
-
{
|
|
181
|
+
{ condition : '/test/foo',
|
|
178
182
|
dispatcher : 'foo-dispatcher'
|
|
179
183
|
},
|
|
180
184
|
'bar':
|
|
181
|
-
{
|
|
185
|
+
{ condition : '/test/bar',
|
|
182
186
|
dispatcher : 'bar-dispatcher' }})
|
|
183
187
|
|
|
184
|
-
let dispatched
|
|
185
|
-
locator.set('foo-dispatcher', { dispatch: () => dispatched = 'foo' })
|
|
186
|
-
locator.set('bar-dispatcher', { dispatch: () => dispatched = 'bar' })
|
|
187
|
-
|
|
188
188
|
const fooResponse = await request.get(`/test/foo`)
|
|
189
189
|
|
|
190
190
|
assert.equal(fooResponse.status, 200, 'Should have received a 200 status')
|
|
@@ -197,14 +197,14 @@ suite('@superhero/http-server', () =>
|
|
|
197
197
|
|
|
198
198
|
test('Can alter the output body', async () =>
|
|
199
199
|
{
|
|
200
|
+
locator.set('foo-dispatcher',
|
|
201
|
+
{ dispatch: (_, session) => session.view.body.foo = 'bar' })
|
|
202
|
+
|
|
200
203
|
server.router.setRoutes(
|
|
201
204
|
{ 'foo':
|
|
202
|
-
{
|
|
205
|
+
{ condition : '/test/foo',
|
|
203
206
|
dispatcher : 'foo-dispatcher' }})
|
|
204
207
|
|
|
205
|
-
locator.set('foo-dispatcher',
|
|
206
|
-
{ dispatch: (_, session) => session.view.body.foo = 'bar' })
|
|
207
|
-
|
|
208
208
|
const response = await request.get(`/test/foo`)
|
|
209
209
|
assert.equal(response.status, 200, 'Should have received a 200 status')
|
|
210
210
|
assert.equal(response.body.foo, 'bar', 'Response body should have been altered')
|
|
@@ -212,11 +212,6 @@ suite('@superhero/http-server', () =>
|
|
|
212
212
|
|
|
213
213
|
test('Can stream HTML5 standard Server-Sent Events (SSE)', async () =>
|
|
214
214
|
{
|
|
215
|
-
server.router.setRoutes(
|
|
216
|
-
{ 'sse':
|
|
217
|
-
{ criteria : '/test/sse',
|
|
218
|
-
dispatcher : 'sse-dispatcher' }})
|
|
219
|
-
|
|
220
215
|
locator.set('sse-dispatcher',
|
|
221
216
|
{ dispatch: (_, session) =>
|
|
222
217
|
{
|
|
@@ -226,6 +221,11 @@ suite('@superhero/http-server', () =>
|
|
|
226
221
|
session.view.stream.end()
|
|
227
222
|
}})
|
|
228
223
|
|
|
224
|
+
server.router.setRoutes(
|
|
225
|
+
{ 'sse':
|
|
226
|
+
{ condition : '/test/sse',
|
|
227
|
+
dispatcher : 'sse-dispatcher' }})
|
|
228
|
+
|
|
229
229
|
const response = await request.get(`/test/sse`)
|
|
230
230
|
|
|
231
231
|
assert.equal(response.status, 200, 'Should have received a 200 status')
|
|
@@ -237,14 +237,14 @@ suite('@superhero/http-server', () =>
|
|
|
237
237
|
|
|
238
238
|
test('Can alter the output headers', async () =>
|
|
239
239
|
{
|
|
240
|
-
server.router.setRoutes(
|
|
241
|
-
{ 'foo':
|
|
242
|
-
{ criteria : '/test/foo',
|
|
243
|
-
dispatcher : 'foo-dispatcher' }})
|
|
244
|
-
|
|
245
240
|
locator.set('foo-dispatcher',
|
|
246
241
|
{ dispatch: (_, session) => session.view.headers.foo = 'bar' })
|
|
247
242
|
|
|
243
|
+
server.router.setRoutes(
|
|
244
|
+
{ 'foo':
|
|
245
|
+
{ condition : '/test/foo',
|
|
246
|
+
dispatcher : 'foo-dispatcher' }})
|
|
247
|
+
|
|
248
248
|
const response = await request.get(`/test/foo`)
|
|
249
249
|
assert.equal(response.status, 200, 'Should have received a 200 status')
|
|
250
250
|
assert.equal(response.headers.foo, 'bar', 'Response header should have been altered')
|
|
@@ -252,28 +252,28 @@ suite('@superhero/http-server', () =>
|
|
|
252
252
|
|
|
253
253
|
test('Can alter the output status', async () =>
|
|
254
254
|
{
|
|
255
|
-
server.router.setRoutes(
|
|
256
|
-
{ 'foo':
|
|
257
|
-
{ criteria : '/test/foo',
|
|
258
|
-
dispatcher : 'foo-dispatcher' }})
|
|
259
|
-
|
|
260
255
|
locator.set('foo-dispatcher',
|
|
261
256
|
{ dispatch: (_, session) => session.view.status = 204 })
|
|
262
257
|
|
|
258
|
+
server.router.setRoutes(
|
|
259
|
+
{ 'foo':
|
|
260
|
+
{ condition : '/test/foo',
|
|
261
|
+
dispatcher : 'foo-dispatcher' }})
|
|
262
|
+
|
|
263
263
|
const response = await request.get(`/test/foo`)
|
|
264
264
|
assert.equal(response.status, 204, 'Should have received a 204 status')
|
|
265
265
|
})
|
|
266
266
|
|
|
267
267
|
test('Can abort the dispatcher', async () =>
|
|
268
268
|
{
|
|
269
|
-
server.router.setRoutes(
|
|
270
|
-
{ 'foo':
|
|
271
|
-
{ criteria : '/test/foo',
|
|
272
|
-
dispatcher : 'foo-dispatcher' }})
|
|
273
|
-
|
|
274
269
|
locator.set('foo-dispatcher',
|
|
275
270
|
{ dispatch: (_, session) => session.abortion.abort(new Error('Aborted')) })
|
|
276
271
|
|
|
272
|
+
server.router.setRoutes(
|
|
273
|
+
{ 'foo':
|
|
274
|
+
{ condition : '/test/foo',
|
|
275
|
+
dispatcher : 'foo-dispatcher' }})
|
|
276
|
+
|
|
277
277
|
const response = await request.get(`/test/foo`)
|
|
278
278
|
|
|
279
279
|
assert.equal(response.status, 500, 'Should have failed with a 500 status')
|
|
@@ -282,11 +282,6 @@ suite('@superhero/http-server', () =>
|
|
|
282
282
|
|
|
283
283
|
test('Can describe an abortion in detail', async () =>
|
|
284
284
|
{
|
|
285
|
-
server.router.setRoutes(
|
|
286
|
-
{ 'foo':
|
|
287
|
-
{ criteria : '/test/foo',
|
|
288
|
-
dispatcher : 'foo-dispatcher' }})
|
|
289
|
-
|
|
290
285
|
locator.set('foo-dispatcher',
|
|
291
286
|
{
|
|
292
287
|
dispatch: (_, session) =>
|
|
@@ -300,6 +295,11 @@ suite('@superhero/http-server', () =>
|
|
|
300
295
|
}
|
|
301
296
|
})
|
|
302
297
|
|
|
298
|
+
server.router.setRoutes(
|
|
299
|
+
{ 'foo':
|
|
300
|
+
{ condition : '/test/foo',
|
|
301
|
+
dispatcher : 'foo-dispatcher' }})
|
|
302
|
+
|
|
303
303
|
const response = await request.get(`/test/foo`)
|
|
304
304
|
|
|
305
305
|
assert.equal(response.status, 500, 'Should have failed with a 500 status')
|
|
@@ -311,11 +311,6 @@ suite('@superhero/http-server', () =>
|
|
|
311
311
|
|
|
312
312
|
test('Can manage thrown errors in the dispatcher', async () =>
|
|
313
313
|
{
|
|
314
|
-
server.router.setRoutes(
|
|
315
|
-
{ 'foo':
|
|
316
|
-
{ criteria : '/test/foo',
|
|
317
|
-
dispatcher : 'foo-dispatcher' }})
|
|
318
|
-
|
|
319
314
|
locator.set('foo-dispatcher',
|
|
320
315
|
{
|
|
321
316
|
dispatch: () =>
|
|
@@ -326,6 +321,11 @@ suite('@superhero/http-server', () =>
|
|
|
326
321
|
}
|
|
327
322
|
})
|
|
328
323
|
|
|
324
|
+
server.router.setRoutes(
|
|
325
|
+
{ 'foo':
|
|
326
|
+
{ condition : '/test/foo',
|
|
327
|
+
dispatcher : 'foo-dispatcher' }})
|
|
328
|
+
|
|
329
329
|
let errorLoggerCalled = false
|
|
330
330
|
|
|
331
331
|
server.log.on('fail', (_, error) =>
|
|
@@ -345,14 +345,14 @@ suite('@superhero/http-server', () =>
|
|
|
345
345
|
|
|
346
346
|
test('Can not mistakenly access the wrong view property', async () =>
|
|
347
347
|
{
|
|
348
|
-
server.router.setRoutes(
|
|
349
|
-
{ 'foo':
|
|
350
|
-
{ criteria : '/test/foo',
|
|
351
|
-
dispatcher : 'foo-dispatcher' }})
|
|
352
|
-
|
|
353
348
|
locator.set('foo-dispatcher',
|
|
354
349
|
{ dispatch: (_, session) => session.view.invalidAttribute })
|
|
355
350
|
|
|
351
|
+
server.router.setRoutes(
|
|
352
|
+
{ 'foo':
|
|
353
|
+
{ condition : '/test/foo',
|
|
354
|
+
dispatcher : 'foo-dispatcher' }})
|
|
355
|
+
|
|
356
356
|
let errorLoggerCalled = false
|
|
357
357
|
|
|
358
358
|
server.log.on('fail', (_, error) =>
|
|
@@ -371,14 +371,13 @@ suite('@superhero/http-server', () =>
|
|
|
371
371
|
|
|
372
372
|
test('Can not mistakenly assign a value to the wrong view property', async () =>
|
|
373
373
|
{
|
|
374
|
-
server.router.setRoutes(
|
|
375
|
-
{ 'foo':
|
|
376
|
-
{ criteria : '/test/foo',
|
|
377
|
-
dispatcher : 'foo-dispatcher' }})
|
|
378
|
-
|
|
379
374
|
locator.set('foo-dispatcher',
|
|
380
375
|
{ dispatch: (_, session) => session.view.invalidAttribute = 'This should not be possible' })
|
|
381
376
|
|
|
377
|
+
server.router.setRoutes(
|
|
378
|
+
{ 'foo':
|
|
379
|
+
{ condition : '/test/foo',
|
|
380
|
+
dispatcher : 'foo-dispatcher' }})
|
|
382
381
|
|
|
383
382
|
let errorLoggerCalled = false
|
|
384
383
|
|
|
@@ -430,17 +429,17 @@ suite('@superhero/http-server', () =>
|
|
|
430
429
|
|
|
431
430
|
fs.rmSync('test', { recursive: true, force: true })
|
|
432
431
|
|
|
432
|
+
locator.set('test-dispatcher',
|
|
433
|
+
{ dispatch: (_, session) => session.view.body.dispatched = true })
|
|
434
|
+
|
|
433
435
|
await assert.doesNotReject(server.bootstrap(
|
|
434
436
|
{ server: { cert, key, minVersion: tlsVersion, maxVersion: tlsVersion },
|
|
435
437
|
router:
|
|
436
438
|
{ routes:
|
|
437
439
|
{ 'test':
|
|
438
|
-
{
|
|
440
|
+
{ condition : '/test',
|
|
439
441
|
dispatcher : 'test-dispatcher' }}}}))
|
|
440
442
|
|
|
441
|
-
locator.set('test-dispatcher',
|
|
442
|
-
{ dispatch: (_, session) => session.view.body.dispatched = true })
|
|
443
|
-
|
|
444
443
|
assert.ok(server.gateway instanceof tls.Server)
|
|
445
444
|
assert.ok(server.http1Server instanceof https.Server)
|
|
446
445
|
assert.ok(server.http2Server?.constructor.name === 'Http2SecureServer')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superhero/http-server",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.7.1",
|
|
4
4
|
"description": "HTTP(S) server component supporting both HTTP 1.1 and HTTP 2.0",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"http server",
|
|
@@ -22,18 +22,21 @@
|
|
|
22
22
|
"./*/*/*/*/*": "./*/*/*/*/*.js",
|
|
23
23
|
"./*/*/*/*/*/*": "./*/*/*/*/*/*.js"
|
|
24
24
|
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"syntax-check": "syntax-check",
|
|
27
|
+
"test": "syntax-check; node --test --test-reporter=@superhero/audit/reporter --experimental-test-coverage"
|
|
28
|
+
},
|
|
25
29
|
"dependencies": {
|
|
26
|
-
"@superhero/router": "
|
|
27
|
-
"@superhero/deep": "
|
|
28
|
-
"@superhero/log": "
|
|
29
|
-
"@superhero/id-name-generator": "
|
|
30
|
+
"@superhero/router": "4.7.1",
|
|
31
|
+
"@superhero/deep": "4.7.1",
|
|
32
|
+
"@superhero/log": "4.7.1",
|
|
33
|
+
"@superhero/id-name-generator": "4.7.1"
|
|
30
34
|
},
|
|
31
35
|
"devDependencies": {
|
|
32
|
-
"@superhero/
|
|
33
|
-
"@superhero/
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"test": "node --trace-warnings --test --experimental-test-coverage"
|
|
36
|
+
"@superhero/audit": "4.7.1",
|
|
37
|
+
"@superhero/syntax-check": "0.0.2",
|
|
38
|
+
"@superhero/locator": "4.7.1",
|
|
39
|
+
"@superhero/http-request": "4.7.1"
|
|
37
40
|
},
|
|
38
41
|
"author": {
|
|
39
42
|
"name": "Erik Landvall",
|
|
@@ -41,6 +44,6 @@
|
|
|
41
44
|
},
|
|
42
45
|
"repository": {
|
|
43
46
|
"type": "git",
|
|
44
|
-
"url": "
|
|
47
|
+
"url": "https://github.com/superhero/http-server.git"
|
|
45
48
|
}
|
|
46
49
|
}
|