|
| 1 | +import 'dart:io' show Platform; // To read environment variables |
| 2 | + |
1 | 3 | import 'package:dart_frog/dart_frog.dart';
|
2 | 4 | import 'package:ht_api/src/middlewares/authentication_middleware.dart';
|
| 5 | +import 'package:shelf_cors_headers/shelf_cors_headers.dart' as shelf_cors; |
3 | 6 |
|
4 | 7 | Handler middleware(Handler handler) {
|
5 |
| - // This middleware applies the `authenticationProvider` to all routes |
| 8 | + // This middleware applies providers and CORS handling to all routes |
6 | 9 | // under /api/v1/.
|
7 |
| - // |
8 |
| - // The `authenticationProvider()` (from `lib/src/middlewares/authentication_middleware.dart`): |
9 |
| - // 1. Attempts to extract a Bearer token from the 'Authorization' header. |
10 |
| - // 2. Validates the token using the `AuthTokenService` (which must be |
11 |
| - // provided by an ancestor middleware, e.g., `routes/_middleware.dart`). |
12 |
| - // 3. Provides the resulting `User?` (nullable User object) into the request |
13 |
| - // context. This makes `context.read<User?>()` available downstream. |
14 |
| - // |
15 |
| - // IMPORTANT: `authenticationProvider()` itself does NOT block unauthenticated |
16 |
| - // requests. It simply makes the user's identity available if authentication |
17 |
| - // is successful. Stricter access control (blocking unauthenticated users) |
18 |
| - // is handled by `requireAuthentication()` middleware applied in more specific |
19 |
| - // route groups (e.g., `/api/v1/data/_middleware.dart`). |
20 |
| - return handler.use(authenticationProvider()); |
| 10 | + |
| 11 | + // --- CORS Configuration --- |
| 12 | + final allowedOriginEnv = Platform.environment['CORS_ALLOWED_ORIGIN']; |
| 13 | + String effectiveOrigin; |
| 14 | + |
| 15 | + if (allowedOriginEnv != null && allowedOriginEnv.isNotEmpty) { |
| 16 | + effectiveOrigin = allowedOriginEnv; |
| 17 | + print( |
| 18 | + '[CORS Middleware] Using Access-Control-Allow-Origin from ' |
| 19 | + 'CORS_ALLOWED_ORIGIN environment variable: "$effectiveOrigin"', |
| 20 | + ); |
| 21 | + } else { |
| 22 | + // IMPORTANT: Default for local development ONLY if env var is not set. |
| 23 | + // You MUST set CORS_ALLOWED_ORIGIN in production for security. |
| 24 | + // This default allows credentials, so it cannot be '*'. |
| 25 | + // Adjust 'http://localhost:3000' if your local Flutter web dev server |
| 26 | + // typically runs on a different port. |
| 27 | + effectiveOrigin = 'http://localhost:3000'; |
| 28 | + print('------------------------------------------------------------------'); |
| 29 | + print('WARNING: CORS_ALLOWED_ORIGIN environment variable is NOT SET.'); |
| 30 | + print( |
| 31 | + 'Defaulting Access-Control-Allow-Origin to: "$effectiveOrigin" ' |
| 32 | + 'FOR DEVELOPMENT ONLY.', |
| 33 | + ); |
| 34 | + print( |
| 35 | + 'For production, you MUST set the CORS_ALLOWED_ORIGIN environment ' |
| 36 | + "variable to your Flutter web application's specific domain.", |
| 37 | + ); |
| 38 | + print('------------------------------------------------------------------'); |
| 39 | + } |
| 40 | + |
| 41 | + final corsConfig = <String, String>{ |
| 42 | + // Use the determined origin (from env var or development default) |
| 43 | + shelf_cors.ACCESS_CONTROL_ALLOW_ORIGIN: effectiveOrigin, |
| 44 | + // Crucial for authenticated APIs where the frontend sends credentials |
| 45 | + // (e.g., Authorization header with fetch({ credentials: 'include' })) |
| 46 | + shelf_cors.ACCESS_CONTROL_ALLOW_CREDENTIALS: 'true', |
| 47 | + // Define allowed HTTP methods |
| 48 | + shelf_cors.ACCESS_CONTROL_ALLOW_METHODS: 'GET, POST, PUT, DELETE, OPTIONS', |
| 49 | + // Define allowed headers from the client |
| 50 | + shelf_cors.ACCESS_CONTROL_ALLOW_HEADERS: |
| 51 | + 'Origin, Content-Type, Authorization, Accept', |
| 52 | + // Optional: How long the results of a preflight request can be cached |
| 53 | + shelf_cors.ACCESS_CONTROL_MAX_AGE: '86400', // 24 hours |
| 54 | + }; |
| 55 | + |
| 56 | + // Apply CORS middleware first. |
| 57 | + // `fromShelfMiddleware` adapts the Shelf-based CORS middleware for Dart Frog. |
| 58 | + var newHandler = handler.use( |
| 59 | + fromShelfMiddleware(shelf_cors.corsHeaders(headers: corsConfig)), |
| 60 | + ); |
| 61 | + |
| 62 | + // Then apply the authenticationProvider. |
| 63 | + // ignore: join_return_with_assignment |
| 64 | + newHandler = newHandler.use(authenticationProvider()); |
| 65 | + |
| 66 | + return newHandler; |
21 | 67 | }
|
0 commit comments