QuadrantServer
A Dart-first, batteries-included HTTP server framework built directly on dart:io with zero external dependencies.
Features
- Dart-first — Named parameters, strong types, null safety
- Functional responses — Handlers return
Responseobjects, never mutate - Declarative config — Everything declared upfront in the
QuadrantServer()constructor - Zero dependencies — Built only on
dart:io - Middleware system — Global and route-level, with short-circuit support
- Path parameters —
/users/:idextracts{'id': '123'} - Built-in middlewares — CORS, logger, and JSON body parser included
Quick Start
import 'package:quadrant_server/quadrant_server.dart';
Future<Response> getUsers(Request req) async {
return Response.ok([
{'id': '1', 'name': 'Ada'},
{'id': '2', 'name': 'Grace'},
]);
}
Future<Response> getUser(Request req) async {
final id = req.params['id'];
return Response.ok({'id': id, 'name': 'Ada'});
}
Future<Response> createUser(Request req) async {
final body = req.body;
return Response.created(body);
}
void main() async {
final app = QuadrantServer(
middlewares: [cors(), logger(), bodyParser()],
routes: [
Route.get(path: '/users', handler: getUsers),
Route.get(path: '/users/:id', handler: getUser),
Route.post(path: '/users', handler: createUser),
],
);
await app.listen(port: 3000);
print('QuadrantServer running on http://localhost:3000');
}
Installation
Add to your pubspec.yaml:
dependencies:
quadrant_server: ^1.0.0
Then run:
dart pub get
Core Concepts
Routes
Define routes using named constructors for each HTTP method:
Route.get(path: '/users', handler: getUsers)
Route.post(path: '/users', handler: createUser)
Route.put(path: '/users/:id', handler: updateUser)
Route.delete(path: '/users/:id', handler: deleteUser)
Route.patch(path: '/users/:id', handler: patchUser)
Request
Immutable wrapper around dart:io HttpRequest:
Future<Response> handler(Request req) async {
req.method; // 'GET', 'POST', etc.
req.path; // '/users/123'
req.params; // {'id': '123'} — path params
req.query; // {'page': '1'} — query string
req.headers; // {'content-type': 'application/json'}
req.body; // {'name': 'Ada'} — parsed JSON (requires bodyParser)
req.raw; // dart:io HttpRequest escape hatch
}
Response
Immutable. Always returned from handlers, never mutated:
Response.ok(data) // 200
Response.created(data) // 201
Response.noContent() // 204
Response.badRequest('message') // 400
Response.unauthorized('message') // 401
Response.forbidden('message') // 403
Response.notFound('message') // 404
Response.internalServerError('msg') // 500
Maps and Lists are automatically JSON-encoded with content-type: application/json.
Middleware
A function that receives a Request and a next() callback:
Middleware auth() {
return (req, next) async {
final token = req.headers['authorization'];
if (token == null) return Response.unauthorized('Missing token');
return next(); // continue to handler
};
}
Apply globally or per-route:
final app = QuadrantServer(
middlewares: [cors(), logger()], // global
routes: [
Route.get(
path: '/admin',
handler: adminHandler,
middlewares: [auth()], // route-level
),
],
docs: true, // endpoint - quadrant_docs
);
Built-in Middlewares
| Middleware | Description |
|---|---|
cors() |
Adds CORS headers. Optional origin parameter (default '*'). |
logger() |
Logs method, path, status code, and response time. |
bodyParser() |
Parses JSON request bodies into req.body. |
Error Handling
final app = QuadrantServer(
routes: [...],
onError: (error, req) => Response.internalServerError(error.toString()),
);
Real-World Example
Check the example/ folder for a production-ready project structure including a Dockerfile for containerized deployment. It demonstrates routing, middleware composition, error handling, and Docker-based deployment in a single runnable app.
Libraries
- quadrant_server
- QuadrantServer — A Dart-first, batteries-included HTTP server framework.