Skip to content

Commit e2adec4

Browse files
committed
update docs
1 parent 7eda882 commit e2adec4

1 file changed

Lines changed: 283 additions & 2 deletions

File tree

README.md

Lines changed: 283 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,283 @@
1-
# middleware
2-
vixcpp/middleware – Standard middlewares for vix.cpp: authentication, CORS, logging, error handling, compression, and rate limiting.
1+
# Vix Middleware
2+
3+
High-performance • Non-blocking • Composable • Production-oriented
4+
5+
The Vix **middleware** module provides a modern, ergonomic middleware system for the **Vix.cpp HTTP runtime**.
6+
It is designed for real applications: security hardening, parsing, auth, request-scoped state, and safe composition.
7+
8+
This module supports **two middleware styles**:
9+
10+
* **Context-based middleware** (`MiddlewareFn`) — preferred
11+
* **Legacy HTTP middleware** (`HttpMiddleware`) — supported via adapters
12+
13+
It also ships with **ready-to-use presets** (CORS, rate limit, CSRF, security headers, IP filtering, parsers, auth, HTTP cache).
14+
15+
---
16+
17+
## Why this module exists
18+
19+
Most C++ “middleware” systems are either:
20+
21+
* too framework-specific
22+
* hard to compose
23+
* blocking by accident
24+
* not explicit about safety (early return, status changes, observable behavior)
25+
26+
Vix middleware is designed to be:
27+
28+
* **explicit**: every middleware decides whether to continue (`next()`) or stop
29+
* **composable**: chain middlewares cleanly
30+
* **safe**: defensive parsing, predictable early returns, no hidden magic
31+
* **fast**: zero-cost abstractions where possible, non-blocking patterns by default
32+
33+
---
34+
35+
## Quick start
36+
37+
Run the full “mega example”:
38+
39+
```bash
40+
vix run examples/http_middleware/mega_middleware_routes.cpp
41+
```
42+
43+
Test quickly:
44+
45+
```bash
46+
curl -i http://127.0.0.1:8080/
47+
curl -i http://127.0.0.1:8080/api/ping -H "x-demo: 1"
48+
curl -i http://127.0.0.1:8080/api/secure/whoami -H "x-api-key: dev_key_123"
49+
curl -i http://127.0.0.1:8080/dev/trace
50+
curl -i http://127.0.0.1:8080/api/cache/demo
51+
curl -i http://127.0.0.1:8080/api/cache/demo -H "x-vix-cache: bypass"
52+
```
53+
54+
---
55+
56+
## Minimal example
57+
58+
### 1) A tiny context-based middleware
59+
60+
```cpp
61+
#include <vix.hpp>
62+
#include <vix/middleware/app/adapter.hpp>
63+
64+
static vix::middleware::MiddlewareFn hello_mw()
65+
{
66+
return [](vix::middleware::Context& ctx, vix::middleware::Next next) {
67+
ctx.res().header("x-hello", "vix");
68+
next();
69+
};
70+
}
71+
72+
int main()
73+
{
74+
vix::App app;
75+
76+
// Adapt ctx middleware into an App middleware
77+
app.use(vix::middleware::app::adapt_ctx(hello_mw()));
78+
79+
app.get("/", [](auto&, auto& res) {
80+
res.send("ok");
81+
});
82+
83+
app.run(8080);
84+
}
85+
```
86+
87+
### 2) A legacy-style middleware (still supported)
88+
89+
```cpp
90+
#include <vix.hpp>
91+
#include <vix/middleware/app/adapter.hpp>
92+
93+
static vix::middleware::HttpMiddleware require_header(std::string key)
94+
{
95+
return [key = std::move(key)](vix::Request& req, vix::Response& res, vix::middleware::Next next) {
96+
if (req.header(key).empty()) {
97+
res.status(401).send("missing header");
98+
return; // do not call next()
99+
}
100+
next();
101+
};
102+
}
103+
104+
int main()
105+
{
106+
vix::App app;
107+
108+
// Adapt legacy middleware into an App middleware
109+
app.use(vix::middleware::app::adapt(require_header("x-demo")));
110+
111+
app.get("/", [](auto&, auto& res) {
112+
res.send("ok");
113+
});
114+
115+
app.run(8080);
116+
}
117+
```
118+
119+
---
120+
121+
## Core concepts
122+
123+
### 1) Context-based middleware (recommended)
124+
125+
A `MiddlewareFn` looks like:
126+
127+
```cpp
128+
(vix::middleware::Context& ctx, vix::middleware::Next next) -> void
129+
```
130+
131+
Rules:
132+
133+
* To continue the pipeline, call `next()`.
134+
* To stop early, do **not** call `next()`.
135+
* You can modify request/response and store request-scoped state.
136+
137+
---
138+
139+
### 2) RequestState (store data across middlewares + handler)
140+
141+
Vix provides type-based request storage (like `std::any`).
142+
143+
```cpp
144+
struct AuthInfo { bool authed{}; std::string role; };
145+
146+
ctx.req().emplace_state<AuthInfo>(AuthInfo{true, "admin"});
147+
148+
if (ctx.req().has_state_type<AuthInfo>()) {
149+
const auto& a = ctx.req().state<AuthInfo>();
150+
}
151+
```
152+
153+
Use it to:
154+
155+
* pass computed data to handlers
156+
* keep auth/session info
157+
* track timings / trace IDs
158+
* attach parsing results
159+
160+
---
161+
162+
### 3) Installation patterns
163+
164+
The app adapter layer provides installation helpers:
165+
166+
* `app.use(mw)` — global
167+
* `install(app, "/prefix/", mw)` — prefix middleware
168+
* `install_exact(app, "/path", mw)` — exact-path middleware
169+
* `chain(mw1, mw2, ...)` — compose middlewares
170+
171+
This is how you build safe and readable route protection:
172+
173+
```cpp
174+
using namespace vix::middleware::app;
175+
176+
install(app, "/api/", rate_limit_dev(120, std::chrono::minutes(1)));
177+
install(app, "/api/secure/", api_key_dev("dev_key_123"));
178+
install(app, "/api/admin/", chain(adapt_ctx(fake_auth()), adapt_ctx(require_admin())));
179+
```
180+
181+
---
182+
183+
## Presets included
184+
185+
The module includes “batteries-included” middleware presets for common needs.
186+
Names may vary slightly depending on your tree, but the example demonstrates:
187+
188+
### Security
189+
190+
* CORS (dev / configurable)
191+
* Security headers
192+
* CSRF (optional)
193+
* IP filtering
194+
195+
### Rate limiting
196+
197+
* Simple in-memory dev limiter (good for local, demos, CI)
198+
199+
### Auth
200+
201+
* API key
202+
* JWT (when enabled)
203+
* RBAC-like gating patterns
204+
205+
### Parsers
206+
207+
* JSON parser
208+
* Form parser
209+
* Multipart parser
210+
* Multipart save (write uploads to disk safely)
211+
212+
### HTTP cache (GET cache)
213+
214+
A cache middleware for GET endpoints, with explicit bypass controls:
215+
216+
* TTL-based caching
217+
* optional bypass header (e.g. `x-vix-cache: bypass`)
218+
* debug headers (e.g. `x-vix-cache-status: hit/miss/bypass`)
219+
220+
---
221+
222+
## Full reference example
223+
224+
The recommended starting point is:
225+
226+
* `examples/http_middleware/mega_middleware_routes.cpp`
227+
228+
It demonstrates:
229+
230+
* routes (GET/POST/etc.)
231+
* global middleware (`App::use`)
232+
* prefix middleware (`install`)
233+
* exact-path middleware (`install_exact`)
234+
* `adapt_ctx()` and `adapt()`
235+
* middleware chaining (`chain`)
236+
* security presets (CORS, headers, CSRF, IP filter)
237+
* rate limiting
238+
* parsers (JSON, form, multipart)
239+
* auth (API key, role gating)
240+
* HTTP cache (GET)
241+
* RequestState patterns
242+
* early return patterns and defensive JSON replies
243+
244+
---
245+
246+
## Directory layout
247+
248+
Typical layout:
249+
250+
```
251+
modules/middleware/
252+
253+
├─ include/vix/middleware/
254+
│ ├─ app/
255+
│ │ ├─ adapter.hpp # adapt_ctx(), adapt(), install(), chain(), ...
256+
│ │ ├─ presets.hpp # cors_dev(), rate_limit_dev(), api_key_dev(), ...
257+
│ │ └─ http_cache.hpp # install_http_cache() + config
258+
│ ├─ Context.hpp
259+
│ ├─ Middleware.hpp
260+
│ └─ ...
261+
262+
└─ examples/
263+
└─ http_middleware/
264+
└─ mega_middleware_routes.cpp
265+
```
266+
267+
---
268+
269+
## Design philosophy
270+
271+
* **Control plane only**: middleware decides flow explicitly.
272+
* **No hidden blocking**: handlers stay short; heavy work should be scheduled.
273+
* **Defensive parsing**: invalid input yields predictable errors.
274+
* **Observable behavior**: trace IDs, debug headers, explicit cache bypass.
275+
* **Composable by default**: chains and prefix installs build readable security.
276+
277+
---
278+
279+
## License
280+
281+
MIT — same as Vix.cpp
282+
283+
Repository: [https://github.com/vixcpp/vix](https://github.com/vixcpp/vix)

0 commit comments

Comments
 (0)