alfred
alfred copied to clipboard
Enchant: Class-Based Middlewares and Endpoint callback
Thanks for this amazing idea! Inspired by this Issue : https://github.com/rknell/alfred/issues/88
With this Mixin we can create class-based middlewares
class _ExampleMiddleware with CallableRequestMixin{
@override
FutureOr call(HttpRequest req, HttpResponse res) {
if (req.headers.value('Authorization') != 'apikey') {
throw AlfredException(401, {'message': 'authentication failed'});
}
}
}
void main() async {
final app = Alfred();
app.all('/example/:id/:name', (req, res) {}, middleware: [_ExampleMiddleware()]);
await app.listen(); //Listening on port 3000
}
and End-Point callback too !
class _RequestController with CallableRequestMixin {
@override
FutureOr call(HttpRequest req, HttpResponse res) => "I'm a Class :)";
}
void main() async {
final app = Alfred();
app.get('/text', _RequestController());
await app.listen(6565); //Listening on port 6565
}
Hey @NathanDraco22! I don't think this makes any sense, as the call
function comes out of the box with every Dart class and does not add any functionality.
And since it is functional without the need for this, I don't know how much sense it makes.
I'm currently using what I've called RouteHandlers, and this is my implementation of them:
import 'dart:async';
import 'package:alfred/alfred.dart';
import 'package:alfredito/src/validators/validators.dart';
import 'package:meta/meta.dart';
part 'controller.dart';
part 'middleware.dart';
/// {@template route_handler}
/// A Route Handler is a class that can be registered as a callback.
/// {@endtemplate}
abstract class RouteHandler<T extends RouteHandler<T>> {
/// Here you can define all your variables that will be available in the
/// route handler.
FutureOr<dynamic> defineVars(HttpRequest req, HttpResponse res) async {}
/// This is the method that is called when the route is.
/// It first creates a new instance of the class itself, then proceeds to
/// call the [defineVars] function so that every variable gets grabbed,
/// and then executes the [run] function.
FutureOr<dynamic> call(HttpRequest req, HttpResponse res) async {
final instance = newInstance;
// this handles the request
await instance.defineVars(req, res);
req.validate();
await instance.run(req, res);
}
/// This is where you should handle all the logic.
FutureOr<dynamic> run(HttpRequest req, HttpResponse res);
/// Creates a new instance of this class (used to avoid usage of dart: mirrors)
T get newInstance;
}
and an example of a controller/middleware:
class ExampleController extends RouteHandler<ExampleController> {
late String apiKey;
@override
FutureOr<void> defineVars(HttpRequest req, HttpResponse res) async {
// here you can grab and process the variables
// that come from the request itself, and save them as vars inside the class
final _apiKey = req.headers.value('Authorization');
if (_apiKey == null || _apiKey.isEmpty) {
throw AlfredException(401, {'message': 'authentication failed'});
}
apiKey = _apiKey;
}
@override
FutureOr<dynamic> run(HttpRequest req, HttpResponse res) async {
// here you can do whatever you want functionality-wise
await res.json(
<String, String>{
'message': 'hello world',
'apiKey': apiKey,
},
);
}
@override
ExampleController get newInstance => ExampleController();
}
Yeah you're right, this Mixin is only like tool or helper, to create a faster function signature. I thought like a Expanded widget in flutter, is only a Flexible with some common settings, This mixin is only like a helper.