@lopatnov/conduit 0.2.0 → 0.3.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/Readme.md +220 -54
- package/bin/native/conduit-aarch64-apple-darwin +0 -0
- package/bin/native/conduit-aarch64-unknown-linux-gnu +0 -0
- package/bin/native/conduit-x86_64-apple-darwin +0 -0
- package/bin/native/conduit-x86_64-pc-windows-msvc.exe +0 -0
- package/bin/native/conduit-x86_64-unknown-linux-gnu +0 -0
- package/bin/native/conduit-x86_64-unknown-linux-musl +0 -0
- package/package.json +18 -4
package/Readme.md
CHANGED
|
@@ -1,99 +1,265 @@
|
|
|
1
1
|
# @lopatnov/conduit
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@lopatnov/conduit)
|
|
4
|
-
[](https://www.npmjs.com/package/@lopatnov/conduit)
|
|
4
|
+
[](https://www.npmjs.com/package/@lopatnov/conduit)
|
|
5
|
+
[](https://github.com/lopatnov/conduit/stargazers)
|
|
6
|
+
[](https://github.com/lopatnov/conduit/blob/main/LICENSE)
|
|
7
|
+
[](https://github.com/lopatnov/conduit)
|
|
5
8
|
|
|
6
|
-
**High-performance reverse proxy and static file server** —
|
|
9
|
+
> **High-performance reverse proxy and static file server** — one JSON config, one binary,
|
|
10
|
+
> zero runtime dependencies.
|
|
7
11
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- Hot-reload in dev and Auto-TLS (Let's Encrypt) in production — [coming soon](https://github.com/lopatnov/conduit#implementation-status)
|
|
12
|
-
- Drop-in upgrade path from `express-reverse-proxy`
|
|
12
|
+
Built on [Cloudflare Pingora](https://github.com/cloudflare/pingora). Routes ~1 trillion
|
|
13
|
+
requests/day in production at Cloudflare. Distributed as a native Rust binary via npm for
|
|
14
|
+
convenience.
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Getting Started
|
|
19
|
+
|
|
20
|
+
**No installation needed:**
|
|
15
21
|
|
|
16
22
|
```bash
|
|
17
|
-
#
|
|
18
|
-
npx @lopatnov/conduit
|
|
23
|
+
npx @lopatnov/conduit init # interactive setup wizard
|
|
24
|
+
npx @lopatnov/conduit # start
|
|
25
|
+
```
|
|
19
26
|
|
|
20
|
-
|
|
27
|
+
**Install globally** — then just type `conduit`:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
21
30
|
npm install -g @lopatnov/conduit
|
|
31
|
+
conduit init
|
|
32
|
+
conduit
|
|
22
33
|
```
|
|
23
34
|
|
|
24
|
-
|
|
25
|
-
platform from [GitHub Releases](https://github.com/lopatnov/conduit/releases).
|
|
35
|
+
> **How it works:** `postinstall` downloads the correct pre-built native binary for your
|
|
36
|
+
> platform from [GitHub Releases](https://github.com/lopatnov/conduit/releases).
|
|
37
|
+
> No compilation. Node.js is only needed for the download step — the server itself is a
|
|
38
|
+
> standalone Rust binary.
|
|
26
39
|
|
|
27
|
-
|
|
40
|
+
---
|
|
28
41
|
|
|
29
|
-
|
|
30
|
-
|
|
42
|
+
## Minimal Config
|
|
43
|
+
|
|
44
|
+
Create `conduit.json`:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"port": 3000,
|
|
49
|
+
"proxy": { "/api": "http://localhost:4000" }
|
|
50
|
+
}
|
|
31
51
|
```
|
|
32
52
|
|
|
33
|
-
|
|
53
|
+
Run:
|
|
34
54
|
|
|
35
55
|
```bash
|
|
36
|
-
# Interactive setup wizard
|
|
37
|
-
conduit init
|
|
38
|
-
|
|
39
|
-
# Start the server
|
|
40
56
|
conduit
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`GET /api/users` → `http://localhost:4000/api/users`. Done.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Common Recipes
|
|
64
|
+
|
|
65
|
+
### Serve static files
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{ "port": 3000, "static": "./dist" }
|
|
69
|
+
```
|
|
41
70
|
|
|
42
|
-
|
|
43
|
-
|
|
71
|
+
### Reverse proxy to a backend
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{ "port": 3000, "proxy": "http://localhost:4000" }
|
|
44
75
|
```
|
|
45
76
|
|
|
46
|
-
|
|
77
|
+
### SPA + API (most common)
|
|
47
78
|
|
|
48
79
|
```json
|
|
49
80
|
{
|
|
50
81
|
"port": 3000,
|
|
51
82
|
"static": "./dist",
|
|
52
|
-
"proxy": { "/api": "http://localhost:4000" }
|
|
83
|
+
"proxy": { "/api": "http://localhost:4000" },
|
|
84
|
+
"fallback": { "status": 200, "file": "./dist/index.html" }
|
|
53
85
|
}
|
|
54
86
|
```
|
|
55
87
|
|
|
56
|
-
|
|
88
|
+
### Dev server with hot reload
|
|
57
89
|
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
conduit shutdown graceful shutdown
|
|
69
|
-
conduit --version
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"port": 3000,
|
|
93
|
+
"logging": "dev",
|
|
94
|
+
"hotReload": true,
|
|
95
|
+
"cors": true,
|
|
96
|
+
"static": "./src",
|
|
97
|
+
"proxy": { "/api": "http://localhost:4000" },
|
|
98
|
+
"fallback": { "status": 200, "file": "./src/index.html" }
|
|
99
|
+
}
|
|
70
100
|
```
|
|
71
101
|
|
|
72
|
-
|
|
102
|
+
### Load-balanced backend with health checks
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"port": 8080,
|
|
107
|
+
"proxy": {
|
|
108
|
+
"/api": {
|
|
109
|
+
"targets": ["http://api1:4000", "http://api2:4000", "http://api3:4000"],
|
|
110
|
+
"strategy": "least-conn",
|
|
111
|
+
"healthCheck": { "path": "/health", "intervalSecs": 10 },
|
|
112
|
+
"retry": { "attempts": 3, "conditions": ["connection_error", "5xx"] }
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Production SPA with Auto-TLS (Let's Encrypt)
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"port": 443,
|
|
123
|
+
"tls": { "acme": { "email": "admin@example.com" } },
|
|
124
|
+
"compression": true,
|
|
125
|
+
"securityHeaders": true,
|
|
126
|
+
"static": "./dist",
|
|
127
|
+
"staticOptions": { "maxAge": "7d", "preCompressed": true },
|
|
128
|
+
"proxy": {
|
|
129
|
+
"/api": {
|
|
130
|
+
"targets": ["http://api1:4000", "http://api2:4000"],
|
|
131
|
+
"strategy": "least-conn",
|
|
132
|
+
"stripPrefix": true,
|
|
133
|
+
"retry": { "attempts": 3, "conditions": ["connection_error", "5xx"] },
|
|
134
|
+
"cache": { "store": "memory", "ttlSecs": 60, "skipIfCookie": true }
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
"rateLimit": { "windowSecs": 60, "limit": 200 },
|
|
138
|
+
"healthCheck": true,
|
|
139
|
+
"metrics": { "path": "/__metrics__", "token": "$METRICS_TOKEN" },
|
|
140
|
+
"fallback": {
|
|
141
|
+
"byAccept": {
|
|
142
|
+
"html": { "status": 200, "file": "./dist/index.html" },
|
|
143
|
+
"json": { "status": 404, "body": { "error": "Not Found" } }
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Multiple sites from one process
|
|
150
|
+
|
|
151
|
+
```json
|
|
152
|
+
[
|
|
153
|
+
{
|
|
154
|
+
"host": "app.example.com",
|
|
155
|
+
"port": 443,
|
|
156
|
+
"tls": { "cert": "$CERT", "key": "$KEY" },
|
|
157
|
+
"static": "./dist",
|
|
158
|
+
"proxy": { "/api": "http://api:4000" }
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"host": "admin.example.com",
|
|
162
|
+
"port": 443,
|
|
163
|
+
"tls": { "cert": "$CERT", "key": "$KEY" },
|
|
164
|
+
"basicAuth": { "users": { "admin": "$ADMIN_PASS" }, "challenge": true },
|
|
165
|
+
"static": "./admin-ui"
|
|
166
|
+
}
|
|
167
|
+
]
|
|
168
|
+
```
|
|
73
169
|
|
|
74
|
-
|
|
75
|
-
| -------- | --------------------- | --------- |
|
|
76
|
-
| Linux | x86-64 | ✅ |
|
|
77
|
-
| Linux | ARM64 | ✅ |
|
|
78
|
-
| macOS | x86-64 (Intel) | ✅ |
|
|
79
|
-
| macOS | ARM64 (Apple Silicon) | ✅ |
|
|
80
|
-
| Windows | x86-64 | ✅ |
|
|
170
|
+
---
|
|
81
171
|
|
|
82
|
-
##
|
|
172
|
+
## CLI Reference
|
|
83
173
|
|
|
84
|
-
|
|
174
|
+
```text
|
|
175
|
+
conduit start server (reads conduit.json)
|
|
176
|
+
conduit -c <file> use a specific config file
|
|
177
|
+
conduit --version print version
|
|
178
|
+
|
|
179
|
+
conduit init interactive setup wizard
|
|
180
|
+
conduit validate validate config (exit 0 = OK)
|
|
181
|
+
conduit probe HEAD each upstream, show latency
|
|
182
|
+
conduit fmt [--write] pretty-print config to stdout or file
|
|
183
|
+
|
|
184
|
+
conduit reload hot-reload config without restart
|
|
185
|
+
conduit status show uptime and inflight requests
|
|
186
|
+
conduit upstreams list upstream health and latency
|
|
187
|
+
conduit upstreams add --route PATH --target URL
|
|
188
|
+
conduit shutdown graceful shutdown
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Features
|
|
194
|
+
|
|
195
|
+
| Feature | Details |
|
|
196
|
+
| --- | --- |
|
|
197
|
+
| **Static files** | ETag, Last-Modified, Range, dotfile control, pre-compressed `.br`/`.gz` |
|
|
198
|
+
| **Compression** | gzip + brotli (async, streaming) |
|
|
199
|
+
| **Reverse proxy** | 7 load-balancing strategies; upstream health checks; retry on failure |
|
|
200
|
+
| **Proxy cache** | Memory, Redis, or disk store; Vary headers; skip-paths |
|
|
201
|
+
| **Auto-TLS** | Let's Encrypt via ACME — automatic issue and renewal |
|
|
202
|
+
| **HTTP/2** | ALPN negotiation; H/2 upstream support |
|
|
203
|
+
| **WebSocket** | Transparent proxying |
|
|
204
|
+
| **Hot config reload** | `conduit reload` — zero-downtime, no restart |
|
|
205
|
+
| **IP filtering** | CIDR allow/deny lists; trust X-Forwarded-For |
|
|
206
|
+
| **Rate limiting** | Token-bucket, keyed by IP or header; Redis-backed for clusters |
|
|
207
|
+
| **Auth** | Basic auth + API key, per-route skip-paths |
|
|
208
|
+
| **CORS** | Origin allow-list, credentials, preflight |
|
|
209
|
+
| **Security headers** | CSP, HSTS, X-Frame-Options, Referrer-Policy |
|
|
210
|
+
| **Health check** | `/__health__` with optional upstream status |
|
|
211
|
+
| **Prometheus** | `/__metrics__` — request counters, duration histograms, cache metrics |
|
|
212
|
+
| **File upload** | `multipart/form-data` — UUID filenames, MIME validation |
|
|
213
|
+
| **Redirects** | Named params (`:slug`), 301/302/307/308 |
|
|
214
|
+
| **Advanced routing** | Glob path + method + header + query predicates |
|
|
215
|
+
| **Virtual hosting** | Multiple sites (`host` matching) in one process |
|
|
216
|
+
| **SPA fallback** | Per-Accept-type fallback rules |
|
|
217
|
+
| **Structured logging** | `dev`, `combined`, `json`, `short`, `common` formats |
|
|
218
|
+
| **Rhai scripting** | Inline middleware scripts for custom logic |
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Supported Platforms
|
|
223
|
+
|
|
224
|
+
| Platform | Architecture |
|
|
225
|
+
| --- | --- |
|
|
226
|
+
| Linux | x86-64 (glibc) |
|
|
227
|
+
| Linux | x86-64 (musl / Docker) |
|
|
228
|
+
| Linux | ARM64 |
|
|
229
|
+
| macOS | Intel (x86-64) |
|
|
230
|
+
| macOS | Apple Silicon (ARM64) |
|
|
231
|
+
| Windows | x86-64 |
|
|
232
|
+
|
|
233
|
+
Unsupported platform? Install from source:
|
|
85
234
|
|
|
86
235
|
```bash
|
|
87
236
|
cargo install lopatnov-conduit
|
|
88
237
|
```
|
|
89
238
|
|
|
90
|
-
|
|
91
|
-
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Links
|
|
242
|
+
|
|
243
|
+
- 📦 [npm package](https://www.npmjs.com/package/@lopatnov/conduit)
|
|
244
|
+
- 🦀 [crates.io package](https://crates.io/crates/lopatnov-conduit)
|
|
245
|
+
- 📖 [Full documentation & source](https://github.com/lopatnov/conduit)
|
|
246
|
+
- 🐛 [Report a bug](https://github.com/lopatnov/conduit/issues)
|
|
247
|
+
- 💬 [Discussions](https://github.com/lopatnov/conduit/discussions)
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Contributing
|
|
252
|
+
|
|
253
|
+
Contributions are welcome! Read [CONTRIBUTING.md](https://github.com/lopatnov/conduit/blob/main/CONTRIBUTING.md)
|
|
254
|
+
before opening a pull request.
|
|
92
255
|
|
|
93
|
-
|
|
256
|
+
Bug reports → [GitHub Issues](https://github.com/lopatnov/conduit/issues).
|
|
257
|
+
Security vulnerabilities → [GitHub Security Advisories](https://github.com/lopatnov/conduit/security/advisories).
|
|
258
|
+
Found it useful? A ⭐ on GitHub helps others discover the project.
|
|
94
259
|
|
|
95
|
-
|
|
260
|
+
---
|
|
96
261
|
|
|
97
262
|
## License
|
|
98
263
|
|
|
99
|
-
[Apache 2.0](https://github.com/lopatnov/conduit/blob/main/LICENSE)
|
|
264
|
+
[Apache 2.0](https://github.com/lopatnov/conduit/blob/main/LICENSE) ©
|
|
265
|
+
2024–2026 [Oleksandr Lopatnov](https://github.com/lopatnov)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lopatnov/conduit",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "High-performance reverse proxy and static file server
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "High-performance reverse proxy and static file server built on Cloudflare Pingora. One JSON config, one binary, no runtime dependencies. TLS, HTTP/2, load balancing, Prometheus metrics, hot reload.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"reverse-proxy",
|
|
7
7
|
"proxy",
|
|
8
|
-
"static-server",
|
|
8
|
+
"static-file-server",
|
|
9
|
+
"web-server",
|
|
10
|
+
"dev-server",
|
|
9
11
|
"http",
|
|
10
12
|
"https",
|
|
11
13
|
"http2",
|
|
14
|
+
"websocket",
|
|
15
|
+
"tls",
|
|
12
16
|
"load-balancer",
|
|
17
|
+
"load-balancing",
|
|
18
|
+
"hot-reload",
|
|
19
|
+
"cors",
|
|
20
|
+
"rate-limiting",
|
|
21
|
+
"prometheus",
|
|
22
|
+
"health-check",
|
|
13
23
|
"rust",
|
|
14
24
|
"pingora"
|
|
15
25
|
],
|
|
16
|
-
"homepage": "https://github.
|
|
26
|
+
"homepage": "https://lopatnov.github.io/conduit/",
|
|
17
27
|
"bugs": {
|
|
18
28
|
"url": "https://github.com/lopatnov/conduit/issues"
|
|
19
29
|
},
|
|
@@ -36,5 +46,9 @@
|
|
|
36
46
|
},
|
|
37
47
|
"engines": {
|
|
38
48
|
"node": ">=18.0.0"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public",
|
|
52
|
+
"registry": "https://registry.npmjs.org/"
|
|
39
53
|
}
|
|
40
54
|
}
|