webhoster 0.3.0 → 0.3.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/package.json
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import * as starter from '../templates/starter.js';
|
|
3
|
+
|
|
4
|
+
async function run() {
|
|
5
|
+
const throwingMiddleware = [() => { throw new Error('brew failed'); }];
|
|
6
|
+
const teapotHandler = {
|
|
7
|
+
onError(transaction) {
|
|
8
|
+
transaction.response.status = 418;
|
|
9
|
+
return "I'm a teapot";
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const listener = await starter.start({ middleware: throwingMiddleware, errorHandlers: [teapotHandler], host: '127.0.0.1', port: 0 });
|
|
14
|
+
try {
|
|
15
|
+
const addr = listener.httpServer.address();
|
|
16
|
+
const port = typeof addr === 'object' ? addr.port : addr;
|
|
17
|
+
const result = await new Promise((resolve, reject) => {
|
|
18
|
+
const req = http.get({ port, path: '/' }, (res) => {
|
|
19
|
+
let data = '';
|
|
20
|
+
res.setEncoding('utf8');
|
|
21
|
+
res.on('data', (c) => { data += c; });
|
|
22
|
+
res.on('end', () => resolve({ status: res.statusCode, body: data }));
|
|
23
|
+
});
|
|
24
|
+
req.on('error', reject);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Print a concise confirmation
|
|
28
|
+
// (CI will show this output in the terminal)
|
|
29
|
+
// eslint-disable-next-line no-console
|
|
30
|
+
console.log('TEAPOT_CHECK_RESULT', JSON.stringify(result));
|
|
31
|
+
} finally {
|
|
32
|
+
await listener.stopHttpServer();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
run().catch((err) => {
|
|
37
|
+
// eslint-disable-next-line no-console
|
|
38
|
+
console.error('check-teapot failed', err);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
});
|
package/templates/starter.js
CHANGED
|
@@ -32,7 +32,9 @@ export async function start(options) {
|
|
|
32
32
|
// Push by reference to allow post modification
|
|
33
33
|
HttpHandler.defaultInstance.middleware.push(options.middleware);
|
|
34
34
|
}
|
|
35
|
-
if (
|
|
35
|
+
if (options.errorHandlers) {
|
|
36
|
+
HttpHandler.defaultInstance.errorHandlers.push(...options.errorHandlers);
|
|
37
|
+
} else {
|
|
36
38
|
HttpHandler.defaultInstance.errorHandlers.push(
|
|
37
39
|
{
|
|
38
40
|
onError() {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import http from 'node:http';
|
|
3
|
+
import HttpListener from '../../helpers/HttpListener.js';
|
|
4
|
+
import HttpHandler from '../../lib/HttpHandler.js';
|
|
5
|
+
import * as starter from '../../templates/starter.js';
|
|
6
|
+
|
|
7
|
+
test.serial('custom error handler returns 418 I\'m a teapot', async (t) => {
|
|
8
|
+
const handler = HttpHandler.defaultInstance;
|
|
9
|
+
const listener = HttpListener.defaultInstance;
|
|
10
|
+
|
|
11
|
+
const mwLen = handler.middleware.length;
|
|
12
|
+
const ehLen = handler.errorHandlers.length;
|
|
13
|
+
|
|
14
|
+
const throwingMiddleware = [() => { throw new Error('brew failed'); }];
|
|
15
|
+
const teapotHandler = {
|
|
16
|
+
onError(transaction) {
|
|
17
|
+
// set custom status and body
|
|
18
|
+
transaction.response.status = 418;
|
|
19
|
+
return "I'm a teapot";
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
await starter.start({ middleware: throwingMiddleware, errorHandlers: [teapotHandler], host: '127.0.0.1', port: 0 });
|
|
24
|
+
|
|
25
|
+
t.truthy(listener.httpServer, 'server started');
|
|
26
|
+
const addr = listener.httpServer.address();
|
|
27
|
+
t.truthy(addr && addr.port, 'server bound');
|
|
28
|
+
|
|
29
|
+
const result = await new Promise((resolve, reject) => {
|
|
30
|
+
const req = http.get({ port: addr.port, path: '/' }, (res) => {
|
|
31
|
+
let data = '';
|
|
32
|
+
res.setEncoding('utf8');
|
|
33
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
34
|
+
res.on('end', () => resolve({ status: res.statusCode, body: data }));
|
|
35
|
+
});
|
|
36
|
+
req.on('error', reject);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
t.is(result.status, 418);
|
|
40
|
+
t.true(result.body.includes("teapot"));
|
|
41
|
+
|
|
42
|
+
await listener.stopHttpServer();
|
|
43
|
+
|
|
44
|
+
// restore global handler state
|
|
45
|
+
handler.middleware.splice(mwLen);
|
|
46
|
+
handler.errorHandlers.splice(ehLen);
|
|
47
|
+
});
|
|
@@ -82,9 +82,9 @@ test.serial('starter.start respects provided errorHandlers and pushes middleware
|
|
|
82
82
|
const lastMw = handler.middleware.at(-1);
|
|
83
83
|
t.is(lastMw, customMiddleware);
|
|
84
84
|
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
t.is(handler.errorHandlers.
|
|
85
|
+
// Provided errorHandlers are appended to the handler.
|
|
86
|
+
t.is(handler.errorHandlers.length, ehLength + customHandlers.length);
|
|
87
|
+
t.is(handler.errorHandlers.at(-1), customHandlers.at(-1));
|
|
88
88
|
|
|
89
89
|
await listener.stopHttpServer();
|
|
90
90
|
|