import 'dart:io'; import 'dart:convert'; import 'package:shelf/shelf.dart'; import 'package:shelf/shelf_io.dart' as shelf_io; import 'package:shelf_multipart/shelf_multipart.dart'; import 'package:shelf_router/shelf_router.dart'; void main() async { // Create a router final router = Router(); // Define routes router.get('/greet', _handleGreet); router.post('/echo', _handleEcho); router.post('/upload', _handleFileUpload); // Create a middleware pipeline final handler = const Pipeline() .addMiddleware(logRequests()) // .addMiddleware(_checkAuthorization()) .addHandler(router); // Start the server final server = await shelf_io.serve(handler, 'localhost', 8080); print('Server listening on port ${server.port}'); } // Handler for the /greet route with query parameters Response _handleGreet(Request request) { final name = request.url.queryParameters['name'] ?? 'stranger'; return Response.ok('Hello, $name!'); } // Handler for the /echo route that handles POST JSON body Future _handleEcho(Request request) async { final payload = await request.readAsString(); final data = jsonDecode(payload) as Map; return Response.ok(jsonEncode(data), headers: {'Content-Type': 'application/json'}); } // Handler for the /upload route that accepts file uploads Future _handleFileUpload(Request request) async { final contentType = request.headers['content-type']; if (contentType == null || !contentType.contains('multipart/form-data')) { return Response(400, body: 'Unsupported content-type'); } if (request.multipart() case var multipart?) { // Iterate over parts making up this request: List uploadedFiles = []; await for (final part in multipart.parts) { // Headers are available through part.headers as a map: final contentDisposition = part.headers['content-disposition']; if (contentDisposition != null && contentDisposition.contains('filename=')) { final name = RegExp(r'name="([^"]*)"').firstMatch(contentDisposition)?.group(1); final filename = RegExp(r'filename="([^"]*)"') .firstMatch(contentDisposition) ?.group(1); if (name != null && filename != null) { final file = File('uploads/$filename'); await file.create(recursive: true); await part.pipe(file.openWrite()); uploadedFiles.add(filename); } } } if (uploadedFiles.isNotEmpty) { return Response.ok('File(s) uploaded: $uploadedFiles'); } { return Response(400, body: 'Unsupported content-type'); } } else { return Response(401); // not a multipart request } } // Custom middleware for authorization Middleware _checkAuthorization() { return (Handler handler) { return (Request request) async { // Protect routes with authorization if ((request.url.path.startsWith('greet') || request.url.path.startsWith('echo') || request.url.path.startsWith('upload')) && request.headers['Authorization'] != 'Bearer mysecrettoken') { return Response.forbidden('Authorization header missing or invalid'); } return handler(request); }; }; }