axon_shelf 0.1.0
axon_shelf: ^0.1.0 copied to clipboard
Shelf middleware adapter for Axon: HTTP request logging for Dart servers. Wraps axon_core's token engine and serializers into a standard Shelf Middleware.
example/main.dart
// ignore_for_file: avoid_print
// ignore_for_file: unused_element
import 'package:axon_shelf/axon_shelf.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_router/shelf_router.dart';
/// Axon + Shelf: minimal runnable example.
///
/// Demonstrates:
/// - Default dev format
/// - Custom format string
/// - JSON serializer (Datadog/ELK-ready)
/// - Custom token registration
/// - Body capture opt-in
/// - Masking sensitive headers
void main() async {
// ── 1. Pick a config ──────────────────────────────────────────────────────
//
// Uncomment the one you want to try.
final config = _devConfig();
// final config = _customFormatConfig();
// final config = _jsonConfig();
// final config = _clfConfig();
// ── 2. Build the handler ──────────────────────────────────────────────────
final router = Router()
..get('/', _root)
..get('/users', _users)
..get('/users/<id>', _user)
..post('/echo', _echo);
final handler = Pipeline()
.addMiddleware(axonShelf(config: config))
.addHandler(router.call);
// ── 3. Serve ──────────────────────────────────────────────────────────────
final server = await io.serve(handler, 'localhost', 8080);
print('▶ Axon example running on http://localhost:${server.port}\n');
print('Try:');
print(' curl http://localhost:8080/');
print(' curl http://localhost:8080/users');
print(' curl http://localhost:8080/users/42');
print(' curl -X POST http://localhost:8080/echo -d \'{"hello":"world"}\'');
}
// ── Configs ───────────────────────────────────────────────────────────────────
/// Default: :method :url :status :response-time ms
/// Output → GET /users 200 4 ms
AxonShelfConfig _devConfig() => const AxonShelfConfig();
/// Custom format with remote address and user-agent.
/// Output → [::1] GET /users 200 4ms | dart:io
AxonShelfConfig _customFormatConfig() => const AxonShelfConfig(
format:
'[:remote-addr] :method :url :status :response-time.ms ms | :user-agent',
);
/// JSON output: ready for Datadog / ELK / Loki.
/// Output → {"ts":"...","method":"GET","url":"/users","status":200,"responseTime":4}
AxonShelfConfig _jsonConfig() => AxonShelfConfig(
serializer: JsonSerializer(
extraFields: const {
'service': 'axon-example',
'env': 'development',
},
),
);
/// Apache Combined Log Format, compatible with Nginx/log parsers.
AxonShelfConfig _clfConfig() =>
const AxonShelfConfig(format: LogFormats.combined);
// ── Handlers ──────────────────────────────────────────────────────────────────
Response _root(Request req) => Response.ok('Axon example server\n');
Response _users(Request req) => Response.ok(
'[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]\n',
headers: {'content-type': 'application/json'},
);
Response _user(Request req, String id) {
final parsed = int.tryParse(id);
if (parsed == null) {
return Response.badRequest(body: 'Invalid id\n');
}
return Response.ok(
'{"id":$parsed,"name":"User $parsed"}\n',
headers: {'content-type': 'application/json'},
);
}
Future<Response> _echo(Request req) async {
final body = await req.readAsString();
return Response.ok(body, headers: {'content-type': 'application/json'});
}