PlusWeb

An Express-style HTTP framework in C++17, on a libuv event loop and the llhttp parser.

One event loop handles every connection, requests resolve through a segment trie keyed on method and path, and no connection went unanswered at any concurrency tested — including the 512 where Express left 264 waiting.

- C++17

- libuv

- llhttp

- CMake

- MIT

mounting rewrites the path, so the sub-router never knows where it was attached.

01 — the parts that are mine

An HTTP framework that starts at the socket.

Express hands you app.get(path, handler) and hides everything under it. I

wanted to know what stands between that call and a file descriptor, so I wrote the whole

path: accept, parse, route, run the middleware chain, serialize, write, and hold the

connection open for the next request.

- 4.8×

- 91.9k

- 6.5 MB

- 55%

02 — against Express, on one box

Add routes to Express and it slows down. This one doesn’t.

Same machine, same handlers, the same load pointed at both. Go from five routes to ten thousand and Express falls from 19,000 requests a second to 355. This one barely moves — and it holds those routes in 6.5 MB of memory where the Express cluster needs 97.7 MB.

03 — run it

Write the routes. Send a request.

Write the handlers and the router rebuilds as you type. Underneath it is

src/trie.cpp itself, compiled for the browser — the method is the

first segment of the key, a literal child always beats a parameter, and nothing backtracks.

send a path

try , ,

the trie these build

- GET /health

- GET /users

- GET /users/new

- GET /users/:id

- POST /users

- DELETE /users/:id

The route lines are compiled by the real router; handler names are decoration.