main.dart 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import 'dart:io';
  2. import 'dart:convert';
  3. import 'package:shelf/shelf.dart';
  4. import 'package:shelf/shelf_io.dart' as shelf_io;
  5. import 'package:shelf_multipart/shelf_multipart.dart';
  6. import 'package:shelf_router/shelf_router.dart';
  7. void main() async {
  8. // Create a router
  9. final router = Router();
  10. // Define routes
  11. router.get('/greet', _handleGreet);
  12. router.post('/echo', _handleEcho);
  13. router.post('/upload', _handleFileUpload);
  14. // Create a middleware pipeline
  15. final handler = const Pipeline()
  16. .addMiddleware(logRequests())
  17. // .addMiddleware(_checkAuthorization())
  18. .addHandler(router);
  19. // Start the server
  20. final server = await shelf_io.serve(handler, 'localhost', 8080);
  21. print('Server listening on port ${server.port}');
  22. }
  23. // Handler for the /greet route with query parameters
  24. Response _handleGreet(Request request) {
  25. final name = request.url.queryParameters['name'] ?? 'stranger';
  26. return Response.ok('Hello, $name!');
  27. }
  28. // Handler for the /echo route that handles POST JSON body
  29. Future<Response> _handleEcho(Request request) async {
  30. final payload = await request.readAsString();
  31. final data = jsonDecode(payload) as Map;
  32. return Response.ok(jsonEncode(data),
  33. headers: {'Content-Type': 'application/json'});
  34. }
  35. // Handler for the /upload route that accepts file uploads
  36. Future<Response> _handleFileUpload(Request request) async {
  37. final contentType = request.headers['content-type'];
  38. if (contentType == null || !contentType.contains('multipart/form-data')) {
  39. return Response(400, body: 'Unsupported content-type');
  40. }
  41. if (request.multipart() case var multipart?) {
  42. // Iterate over parts making up this request:
  43. List<String> uploadedFiles = [];
  44. await for (final part in multipart.parts) {
  45. // Headers are available through part.headers as a map:
  46. final contentDisposition = part.headers['content-disposition'];
  47. if (contentDisposition != null &&
  48. contentDisposition.contains('filename=')) {
  49. final name =
  50. RegExp(r'name="([^"]*)"').firstMatch(contentDisposition)?.group(1);
  51. final filename = RegExp(r'filename="([^"]*)"')
  52. .firstMatch(contentDisposition)
  53. ?.group(1);
  54. if (name != null && filename != null) {
  55. final file = File('uploads/$filename');
  56. await file.create(recursive: true);
  57. await part.pipe(file.openWrite());
  58. uploadedFiles.add(filename);
  59. }
  60. }
  61. }
  62. if (uploadedFiles.isNotEmpty) {
  63. return Response.ok('File(s) uploaded: $uploadedFiles');
  64. }
  65. {
  66. return Response(400, body: 'Unsupported content-type');
  67. }
  68. } else {
  69. return Response(401); // not a multipart request
  70. }
  71. }
  72. // Custom middleware for authorization
  73. Middleware _checkAuthorization() {
  74. return (Handler handler) {
  75. return (Request request) async {
  76. // Protect routes with authorization
  77. if ((request.url.path.startsWith('greet') ||
  78. request.url.path.startsWith('echo') ||
  79. request.url.path.startsWith('upload')) &&
  80. request.headers['Authorization'] != 'Bearer mysecrettoken') {
  81. return Response.forbidden('Authorization header missing or invalid');
  82. }
  83. return handler(request);
  84. };
  85. };
  86. }