# Middleware

* [Middleware](/1.x/the-basics/middleware.md#middleware)
  * [Denying Requests via Middleware](/1.x/the-basics/middleware.md#denying-requests-via-middleware)
  * [Declaring Middleware](/1.x/the-basics/middleware.md#declaring-middleware)
  * [Named Middleware](/1.x/the-basics/middleware.md#named-middleware)
  * [Global Middleware](/1.x/the-basics/middleware.md#global-middleware)
  * [`waterfall([...])`](/1.x/the-basics/middleware.md#waterfall)
  * [\*\*Maintaining Code Readability](/1.x/the-basics/middleware.md#maintaining-code-readability)
* [Next Up...](/1.x/the-basics/middleware.md#next-up)

## Middleware

Sometimes, it becomes to recycle code to run on multiple routes. Angel allows for this in the form of *middleware*. Middleware are frequently used as authorization filters, or to serialize database data for use in subsequent routes. Middleware in Angel can be any route handler, whether a function or arbitrary data. You can also throw exceptions in middleware.

### Denying Requests via Middleware

A middleware should return either `true` or `false`. If `false` is returned, no further routes will be executed. If `true` is returned, route evaluation will continue. (more on request handler return values [here](/1.x/the-basics/requests-and-responses.md#return-values)).

As you can imagine, this is perfect for authorization filters.

### Declaring Middleware

You can call a router's `chain` method (**recommended!**), or assign middleware in the `middleware` parameter of a route method.

```dart
// Both ways ultimately accomplish the same thing

app
  .chain((req, res) {
    res.write("Hello, ");
    return true;
  }).get('/', 'world!');

app.get('/', 'world!', middleware: [someListOfMiddleware]);
```

### Named Middleware

`Router` instances allow you to assign names to middleware via `registerMiddleware`. After registering a middleware, you can include it in a route just by passing its name into the `middleware` array. If you are `mount`-ing another `Routable` or `Angel` instance, you can map all its middleware into a namespace by passing it to the `use` call.

```dart
app.registerMiddleware('deny', (req, res) async => false);
app.get('/no', 'This will never show', middleware: ['deny']);

// Using annotation
@Middleware(const ['deny'])
Future never(RequestContext req, ResponseContext res) async {
  return "This will never show either";
}

app.get('/yes', never);

// Using a middleware namespace
Angel parent = new Angel();
parent.use('/child', app, middlewareNamespace: 'child');
parent.get('/foo', 'Never shown', middleware: ['child.deny']);
```

### Global Middleware

To add a handler that handles *every* request, call `app.use`. This is equivalent to calling `app.all('*', <handler>)`. (more info on request lifecycle [here](/1.x/the-basics/request-lifecycle.md)).

```dart
app.use((req, res) async => res.end());
```

For more complicated middleware, you can also create a class:

```dart
class MyMiddleware {
  Future<bool> call(Angel app) async {
    // Do something...
  }
}
```

Canonically, when using a class as a request handler, it should provide a `handleRequest(RequestContext, ResponseContext)` method. This pattern is seen throughout many Angel plugins, such as `VirtualDirectory` or `Proxy`.

The reason for this is that a name like `handleRequest` makes it very clear to anyone reading the code what it is supposed to do. This is the same rationale behind [controllers](/1.x/the-basics/controllers.md) providing a `configureServer` method.

```dart
class MyCanonicalHandler {
 Future<bool> handleRequest(RequestContext req, ResponseContext res) async {
  // Do something cool...
 }
}

app.use(new MyCanonicalHandler().handleRequest);
```

### waterfall

You can chain middleware (or any request handler together), if you do not feel like making multiple `chain` calls, or if it is impossible to call chain multiple times, using the [`waterfall`](https://www.dartdocs.org/documentation/angel_framework/latest/angel_framework/waterfall.html) function:

```dart
app.chain(waterfall([
  banIp('127.0.0.1'),
  'auth',
  ensureUserHasAccess(),
  (req, res) async => true,
  takeOutTheTrash()
])).get(...);
```

### Maintaining Code Readability

Note that a cleaner representation is:

```dart
app.get('/the-route', waterfall([
  banIp('127.0.0.1'),
  'auth',
  ensureUserHasAccess(),
  (req, res) async => true,
  takeOutTheTrash()
  (req, res) {
   // Your route handler here...
  }
]));
```

In general, consider it a code smell to stack multiple handlers onto a route like this; it hampers readability, and in general just doesn't look good.

Instead, when you have multiple handlers, you can split them into multiple `waterfall` calls, assigned to variables, which have the added benefit of communicating what each set of middleware does:

```dart
var authorizationMiddleware = waterfall([
 banIp('127.0.0.1'),
 requireAuthentication(),
 ensureUserHasAccess(),
]);

var someOtherMiddleware = waterfall([
 (req, res) async => true,
 takeOutTheTrash(),
]);

var theActualRouteHandler = (req, res) async {
 // Handle the request...
};

app.get('/the-route', waterfall([
 authorizationMiddleware,
 someOtherMiddleware,
 theActualRouteHandler,
]);
```

**Tip**: Prefer using named functions as handlers, rather than anonymous functions, or concrete objects.

## Next Up...

Take a good look at [controllers](/1.x/the-basics/controllers.md) in Angel!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.angel-dart.dev/1.x/the-basics/middleware.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
