mock_http_server 1.0.0
mock_http_server: ^1.0.0 copied to clipboard
A modern, enterprise-grade HTTP, HTTPS, and WebSocket mock server package for Dart and Flutter. Support queue-based matching, path/regex routing, middleware, delay/bandwidth simulation, GraphQL operat [...]
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:mock_http_server/mock_http_server.dart';
void main() async {
print('Starting MockForge Demo Server...');
// 1. Initialize MockWebServer
final server = MockWebServer();
server.debug = true; // Enables pretty console logging
// 2. Register Logging and Auth Middleware
server.addMiddleware(const LoggingMiddleware(printHeaders: true));
// Set up API Key protection on requests
server.addMiddleware(AuthMiddleware.apiKey('X-Api-Key', 'secret-key-123'));
// 3. Configure a RouteDispatcher for routing endpoints
final router = RouteDispatcher();
server.dispatcher = router;
// Endpoint: Basic GET
router.get('/api/status', (RecordedRequest request) {
return MockResponse()
.setStatusCode(200)
.setHeader('Content-Type', 'application/json')
.setBody('{"status": "healthy", "uptime": "99.9%"}');
});
// Endpoint: Dynamic Route Parameters
router.get('/api/users/:id', (RecordedRequest request) {
final params = request.pathParameters('/api/users/:id');
final userId = params['id'] ?? 'unknown';
return MockResponse()
.setStatusCode(200)
.setHeader('Content-Type', 'application/json')
.setBody('{"id": "$userId", "name": "Developer $userId"}');
});
// Endpoint: Network Simulation (Delay + Throttling)
router.get('/api/download', (RecordedRequest request) {
final largeString = 'A' * 50000; // 50 KB of data
return MockResponse()
.setStatusCode(200)
.setHeader('Content-Type', 'text/plain')
.setBody(largeString)
.withDelay(const Duration(milliseconds: 500)) // 500ms startup delay
.throttle(10240); // Restrict to 10 KB/s download speed
});
// Endpoint: Server-Sent Events (SSE)
router.get('/api/events', (RecordedRequest request) {
final controller = StreamController<SseEvent>();
int counter = 0;
Timer.periodic(const Duration(milliseconds: 300), (timer) {
if (counter >= 5) {
timer.cancel();
controller.close();
} else {
counter++;
controller.add(SseEvent(
event: 'ticker',
data: 'Tick count #$counter',
id: counter.toString(),
));
}
});
return SseResponseBuilder.build(controller.stream);
});
// 4. WebSocket setup
server.webSocketHandler.register('/ws/chat', (MockWebSocketConnection connection) {
print('WebSocket client connected!');
connection.send('Welcome to MockForge chat!');
// Echo back messages or auto reply
connection.addAutoReplyString('ping', 'pong');
connection.stream.listen((dynamic message) {
print('WebSocket received: $message');
if (message != 'ping') {
connection.send('Echo: $message');
}
});
});
// 5. Start the mock server on a dynamic port
await server.start();
print('MockForge server running at: ${server.url}');
// --- CLIENT SIMULATIONS ---
final client = http.Client();
final commonHeaders = {'X-Api-Key': 'secret-key-123'};
try {
// Client Request: Basic Status
print('\n[Client] Fetching Status...');
final statusRes = await client.get(Uri.parse('${server.url}api/status'), headers: commonHeaders);
print('[Client] Status code: ${statusRes.statusCode}, body: ${statusRes.body}');
// Client Request: Path Parameters
print('\n[Client] Fetching User 42...');
final userRes = await client.get(Uri.parse('${server.url}api/users/42'), headers: commonHeaders);
print('[Client] User body: ${userRes.body}');
// Client Request: Throttling simulation
print('\n[Client] Initiating throttled download...');
final stopwatch = Stopwatch()..start();
final downloadRes = await client.get(Uri.parse('${server.url}api/download'), headers: commonHeaders);
stopwatch.stop();
print('[Client] Downloaded ${downloadRes.body.length} bytes in ${stopwatch.elapsed.inSeconds} seconds.');
// Client Request: SSE Events Stream
print('\n[Client] Reading SSE Event Stream...');
final request = http.Request('GET', Uri.parse('${server.url}api/events'))..headers.addAll(commonHeaders);
final response = await client.send(request);
await response.stream.transform(utf8.decoder).listen((line) {
if (line.trim().isNotEmpty) {
print('[Client SSE] $line');
}
}).asFuture<void>();
} finally {
client.close();
print('\nShutting down MockForge Server...');
await server.shutdown();
print('Server cleanly stopped.');
}
}