# Hooks We have already seen how to add some "hooks" to the application using the Route Lifecycle Hooks, but Serinus also provides a way to create custom hooks that can be used to execute code at specific points in the request lifecycle. These hooks are similar to middlewares, but way more powerful. They can be used to execute code before and after the request is handled, but also before the request is received and after the response is sent. This can be useful to authenticate users, log requests, and responses, and more. Also, hooks can expose services to the application, so you can use them to create global services that can be used in the route handlers. As for the Routes, Hooks are `Hookable` objects, so they can use the lifecycle hooks provided by the mixins and even some specific hooks provided by the `Hook` class. | Mixin | Hook | Description | |-------|------|-------------| | OnRequest | `onRequest` | Executes code when the request is received | | OnBeforeHandle | `beforeHandle` | Executes code before the request is handled. | | OnAfterHandle | `afterHandle` | Executes code after the request is handled. | | OnResponse | `onResponse` | Executes code when the response is sent. | In the example below, we create a custom hook that logs the request and response. ```dart import 'package:serinus/serinus.dart'; class LogHook extends Hook with OnRequest, OnBeforeHandle, OnAfterHandle, OnResponse { @override Future onRequest(Request request, InternalResponse response) async { print('Request received: ${request.method} ${request.url}'); } @override Future beforeHandle(RequestContext context) async { print('Before handling the request'); } @override Future afterHandle(RequestContext context, WrappedResponse response) async { print('After handling the request'); } @override Future onResponse( Request request, WrappedResponse data, ResponseProperties properties) async { print('Response sent: ${data}'); } } ``` ## Built-in Hooks Serinus provides some built-in hooks that can be used to add some common functionalities to the application. | Hook | Description | |------|-------------| | `BodySizeLimit` | Limit the size of the body of the request | | `SecureSessionHook` | Allow the usage of a secure session instead of the common one | | `CorsHook` | Enable Cors headers in the application | ## Expose a Service Hooks can also expose services to the application. This can be done by overriding the `service` getter in the hook class. ```dart import 'package:serinus/serinus.dart'; class LogHook extends Hook { @override MyService get service => MyService(); } class MyService { void doSomething() { print('Doing something'); } } ``` In the example above, the `LogHook` class exposes a `MyService` object to the application. This service will behave as a global provider and will be accessible using the `use` method on the `RequestContext` object. ## Add a Hook to the Application Now we have a good understainding of how Hooks work and how to create them, let's see how to add them to the application. This can be done using the `use` method on the `SerinusApplication` object. ```dart import 'package:serinus/serinus.dart'; Future main() async { final app = await serinus.createApplication( entrypoint: AppModule() ); // Add the hook to the application app.use(LogHook()); // Start the application await app.serve(); } ``` And that's it! Now the `LogHook` is added to the application and will be executed at the specified points in the request lifecycle. ## Add a Hook to the Controller You can also add hooks to a specific controller using the `hooks` property of the `Controller` class. ```dart import 'package:serinus/serinus.dart'; class TestController extends Controller { TestController() { hooks.add(LogHook()); } } ``` ## Add a Hook to a Route You can also add hooks to a specific route using the `hooks` property of the `Route` class. ```dart import 'package:serinus/serinus.dart'; class TestController extends Controller { TestController() : super('/test') { on(Route.get('/', getTest)..hooks.add(LogHook())); } Future getTest(RequestContext context) async { return 'Test'; } } ```