simple-http-bin 0.1.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.
Files changed (3) hide show
  1. package/README.md +45 -0
  2. package/cli.js +96 -0
  3. package/package.json +25 -0
package/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # simple-http-bin
2
+
3
+ A tiny local httpbin-like utility.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g simple-http-bin
9
+ ```
10
+
11
+ ## Run
12
+
13
+ ```bash
14
+ simple-http-bin
15
+ ```
16
+
17
+ Or:
18
+
19
+ ```bash
20
+ npx simple-http-bin
21
+ ```
22
+
23
+ ## Options
24
+
25
+ ```bash
26
+ simple-http-bin --port 8080
27
+ simple-http-bin -p 8080
28
+ PORT=8080 simple-http-bin
29
+ HOST=0.0.0.0 simple-http-bin
30
+ ```
31
+
32
+ ## Endpoints
33
+
34
+ - `GET /` show help text
35
+ - `GET /headers` echo request headers as JSON
36
+ - `ANY /anything` echo method, path, query, headers, and body
37
+ - `ANY /status/:code` return the given HTTP status code
38
+
39
+ ## Example
40
+
41
+ ```bash
42
+ curl http://127.0.0.1:51234/headers
43
+ curl -X POST http://127.0.0.1:51234/anything -d "hello"
44
+ curl -i http://127.0.0.1:51234/status/418
45
+ ```
package/cli.js ADDED
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+
3
+ const http = require('node:http');
4
+
5
+ const DEFAULT_PORT = 51234;
6
+ const args = process.argv.slice(2);
7
+ const portFlagIndex = args.findIndex((arg) => arg === '--port' || arg === '-p');
8
+ const cliPort = portFlagIndex >= 0 ? Number(args[portFlagIndex + 1]) : Number(args[0]);
9
+ const envPort = Number(process.env.PORT);
10
+ const port = Number.isInteger(cliPort) && cliPort > 0 ? cliPort : Number.isInteger(envPort) && envPort > 0 ? envPort : DEFAULT_PORT;
11
+ const host = process.env.HOST || '127.0.0.1';
12
+
13
+ function sendJson(res, statusCode, payload) {
14
+ const body = JSON.stringify(payload, null, 2);
15
+ res.writeHead(statusCode, {
16
+ 'Content-Type': 'application/json; charset=utf-8',
17
+ 'Content-Length': Buffer.byteLength(body),
18
+ });
19
+ res.end(body);
20
+ }
21
+
22
+ function readBody(req) {
23
+ return new Promise((resolve) => {
24
+ const chunks = [];
25
+ req.on('data', (chunk) => chunks.push(chunk));
26
+ req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
27
+ req.on('error', () => resolve(''));
28
+ });
29
+ }
30
+
31
+ function helpText(baseUrl) {
32
+ return [
33
+ 'simple-http-bin',
34
+ '',
35
+ `Running at: ${baseUrl}`,
36
+ `Port: ${port} (use --port <n> or PORT=<n>)`,
37
+ '',
38
+ 'Endpoints:',
39
+ ' GET / Show this help text',
40
+ ' GET /headers Echo request headers as JSON',
41
+ ' ANY /anything Echo method, path, query, headers, and body',
42
+ ' ANY /status/:n Return the given HTTP status code',
43
+ '',
44
+ 'Examples:',
45
+ ` curl ${baseUrl}/headers`,
46
+ ` curl -X POST ${baseUrl}/anything -d "hello"`,
47
+ ` curl -i ${baseUrl}/status/418`,
48
+ ].join('\n');
49
+ }
50
+
51
+ const server = http.createServer(async (req, res) => {
52
+ const url = new URL(req.url, `http://${req.headers.host || `${host}:${port}`}`);
53
+ const path = url.pathname;
54
+
55
+ if (req.method === 'GET' && path === '/') {
56
+ res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
57
+ res.end(helpText(`http://${host}:${port}`));
58
+ return;
59
+ }
60
+
61
+ if (path === '/headers') {
62
+ sendJson(res, 200, { headers: req.headers });
63
+ return;
64
+ }
65
+
66
+ if (path.startsWith('/status/')) {
67
+ const code = Number(path.split('/')[2]);
68
+ res.writeHead(Number.isInteger(code) ? code : 400, { 'Content-Type': 'text/plain; charset=utf-8' });
69
+ res.end(`status ${Number.isInteger(code) ? code : 400}`);
70
+ return;
71
+ }
72
+
73
+ if (path === '/anything') {
74
+ const body = await readBody(req);
75
+ sendJson(res, 200, {
76
+ method: req.method,
77
+ path,
78
+ query: Object.fromEntries(url.searchParams.entries()),
79
+ headers: req.headers,
80
+ body,
81
+ });
82
+ return;
83
+ }
84
+
85
+ res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });
86
+ res.end('not found');
87
+ });
88
+
89
+ server.listen(port, host, () => {
90
+ const baseUrl = `http://${host}:${port}`;
91
+ console.log(helpText(baseUrl));
92
+ });
93
+
94
+ process.on('SIGINT', () => {
95
+ server.close(() => process.exit(0));
96
+ });
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "simple-http-bin",
3
+ "version": "0.1.0",
4
+ "description": "A tiny local httpbin-like utility",
5
+ "license": "MIT",
6
+ "keywords": [
7
+ "httpbin",
8
+ "http",
9
+ "cli",
10
+ "server"
11
+ ],
12
+ "files": [
13
+ "cli.js",
14
+ "README.md"
15
+ ],
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "bin": {
20
+ "simple-http-bin": "cli.js"
21
+ },
22
+ "engines": {
23
+ "node": ">=18"
24
+ }
25
+ }