UNPKG

2.85 kBJavaScriptView Raw
1'use strict'
2
3const { red } = require('./detect/colors')
4const { check } = require('./mapping')
5const dispatcher = require('./dispatcher')
6const {
7 $configuration,
8 $configurationEventEmitter,
9 $configurationRequests,
10 $mappingChecked,
11 $requestId,
12 $requestInternal
13} = require('./symbols')
14
15async function checkMappings (configuration, mappings) {
16 for await (const mapping of mappings) {
17 if (!mapping[$mappingChecked]) {
18 await check(configuration, mapping)
19 }
20 }
21}
22
23module.exports = class IConfiguration {
24 constructor (configuration) {
25 this[$configuration] = configuration
26 }
27
28 get handlers () {
29 return Object.assign({}, this[$configuration].handlers)
30 }
31
32 get mappings () {
33 return [].concat(this[$configuration].mappings)
34 }
35
36 get http2 () {
37 return this[$configuration].http2
38 }
39
40 get protocol () {
41 return this[$configuration].protocol
42 }
43
44 async setMappings (mappings, request, timeout = 5000) {
45 const configuration = this[$configuration]
46 await checkMappings(configuration, mappings)
47 const configurationRequests = configuration[$configurationRequests]
48 const contexts = [...configurationRequests.contexts]
49 const requestContext = contexts.filter(({ request: candidate }) => candidate === request)[0]
50 const requestsHolding = contexts.filter(candidate => candidate !== requestContext).map(({ holding }) => holding)
51 const holding = Promise.race([
52 Promise.all(requestsHolding),
53 new Promise((resolve, reject) => setTimeout(() => {
54 reject(new Error('iconfiguration.setMappings appears to be blocked'))
55 }, timeout))
56 ])
57 .then(() => {
58 configuration.mappings = mappings
59 })
60 configurationRequests.holding = holding.then(undefined, () => {}) // Absorb error to unblock server
61 holding.then(undefined, () => {
62 console.log(red('REserve blocked during configuration.setMappings'))
63 console.table(contexts.map(context => {
64 const { emitParameters, request, released } = context
65 let info
66 if (emitParameters.statusCode) {
67 info = { statusCode: emitParameters.statusCode }
68 } else if (released) {
69 info = 'exclude-from-holding-list'
70 } else if (context === requestContext) {
71 info = 'configure.setMappings'
72 } else {
73 info = { ms: (new Date() - emitParameters.start) } // + ' ms'
74 }
75 return {
76 id: request[$requestId],
77 method: request.method,
78 url: request.url,
79 info
80 }
81 }))
82 })
83 return holding
84 }
85
86 dispatch (request, response) {
87 const configuration = this[$configuration]
88 const eventEmitter = configuration[$configurationEventEmitter]
89 request[$requestInternal] = true
90 return dispatcher.call(eventEmitter, configuration, request, response)
91 }
92}