În mod tradițional, Dart a fost privit exclusiv ca un limbaj pentru client și aplicații mobile Flutter. Cu toate acestea, în ultimii ani, adoptarea Dart pe server a crescut exponențial în arhitecturile enterprise. Motivul este strategic: partajarea integrală a codului de domeniu, a entităților de date și a validărilor de afaceri între aplicația client Flutter și backend, eliminând complet munca duplicată și discrepanțele dintre echipe.
Pentru dezvoltarea backend-urilor de înaltă performanță, ecosistemul oficial Dart pune la dispoziție Shelf: un framework HTTP minimalist, modular și compozabil, inspirat din Rack (Ruby) și Connect (Node.js), bazat pe un pipeline asincron de Middleware și Handler.
# Cerere HTTP Sosită de la Client
# │
# ▼
# ┌─────────────────────────────────────────────────────────┐
# │ Pipeline Shelf │
# │ ├── Middleware 1: Logging & Corelație (X-Request-ID) │
# │ ├── Middleware 2: Securitate CORS & Content-Type │
# │ └── Middleware 3: Autentificare JWT / Bearer Token │
# └────────────────────────────┬────────────────────────────┘
# │
# ▼
# ┌─────────────────────────────────────────────────────────┐
# │ shelf_router (Dispecer Rute REST) │
# │ ├── GET /api/v1/health ──► Handler Sănătate │
# │ ├── GET /api/v1/users ──► Controller Utilizatori │
# │ └── POST /api/v1/orders ──► Controller Comenzi │
# └────────────────────────────┬────────────────────────────┘
# │
# ▼
# Răspuns HTTP JSON Generat Rapid (<5ms)
Tabel Comparativ: Dart Shelf vs Node.js Express vs Go (Gin)
| Criteriu Tehnic | Dart Shelf (Compilat AOT) | Node.js (Express) | Go (Gin Framework) |
|---|---|---|---|
| Mod Compilare | Ahead-Of-Time (Binar Nativ) | Just-In-Time (V8 Engine) | Ahead-Of-Time (Binar Nativ) |
| Timp de Pornire (Cold Start) | Sub 25 milisecunde | 300 – 800 ms | Sub 15 milisecunde |
| Amprentă Memorie RAM (Idle) | 15 – 30 MB RAM | 70 – 130 MB RAM | 10 – 25 MB RAM |
| Siguranță Tipuri | Totală (Sound Null Safety + Dart 3) | Opțională (doar prin TypeScript) | Totală (Static tipizat) |
| Partajare Cod cu Frontend | 100% (Identic cu Flutter) | Doar cu React/Vue (JS/TS) | Zero (Baze de cod separate) |
import 'dart:convert';
import 'dart:io';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_router/shelf_router.dart';
// 1. Middleware de Autentificare prin Bearer Token
Middleware checkAuthToken() {
return (Handler innerHandler) {
return (Request request) async {
// Endpoint-urile publice nu necesită autentificare:
if (request.url.path == 'health' || request.url.path.startsWith('public')) {
return innerHandler(request);
}
final authHeader = request.headers['Authorization'];
if (authHeader == null || !authHeader.startsWith('Bearer ')) {
return Response(HttpStatus.unauthorized,
body: jsonEncode({'error': 'Token de autentificare lipsă'}),
headers: {'content-type': 'application/json'});
}
final token = authHeader.substring(7);
if (token != 'secret-api-token-123') {
return Response(HttpStatus.forbidden,
body: jsonEncode({'error': 'Token invalid sau expirat'}),
headers: {'content-type': 'application/json'});
}
return innerHandler(request);
};
};
}
// 2. Definirea Rutelor cu shelf_router
Router createApiRouter() {
final router = Router();
// Health check pentru Kubernetes Liveness Probe:
router.get('/health', (Request request) {
return Response.ok(
jsonEncode({'status': 'UP', 'engine': 'Dart-Shelf-AOT', 'version': '3.0'}),
headers: {'content-type': 'application/json'},
);
});
// Creare resursă asincronă cu validare:
router.post('/api/v1/orders', (Request request) async {
try {
final payload = await request.readAsString();
final data = jsonDecode(payload) as Map;
final amount = data['amount'] as num?;
if (amount == null || amount <= 0) {
return Response.badRequest(
body: jsonEncode({'error': 'Valoarea comenzii trebuie să fie pozitivă'}),
headers: {'content-type': 'application/json'},
);
}
final responseData = {
'orderId': 'ORD-${DateTime.now().millisecondsSinceEpoch}',
'amount': amount,
'status': 'CONFIRMED',
};
return Response(HttpStatus.created,
body: jsonEncode(responseData),
headers: {'content-type': 'application/json'});
} catch (e) {
return Response.internalServerError(
body: jsonEncode({'error': 'Eroare internă de procesare JSON'}),
headers: {'content-type': 'application/json'},
);
}
});
return router;
}
Future main() async {
final port = int.parse(Platform.environment['PORT'] ?? '8080');
// Pipeline complet cu Middleware compus:
final handler = const Pipeline()
.addMiddleware(logRequests())
.addMiddleware(checkAuthToken())
.addHandler(createApiRouter().call);
final server = await shelf_io.serve(handler, InternetAddress.anyIPv4, port);
print('Server Dart Shelf activ pe portul http://${server.address.host}:${server.port}');
}
# Etapa 1: Compilare binar nativ AOT cu SDK-ul oficial Dart
FROM dart:stable AS build
WORKDIR /app
COPY pubspec.* ./
RUN dart pub get
COPY . .
RUN dart pub get --offline
RUN dart compile exe bin/server.dart -o bin/server
# Etapa 2: Imagine de rulare Distroless ultra-minimală și securizată
FROM gcr.io/distroless/base-debian12
COPY --from=build /app/bin/server /app/bin/server
EXPOSE 8080
USER nonroot:nonroot
ENTRYPOINT ["/app/bin/server"]