### ----------------------------------------------------
### -- cro
### -- Licenses: Artistic-2.0
### -- Authors: Jonathan Worthington <jnthn@jnthn.net>
### -- File: docs/reference/cro-http-router.md
### ----------------------------------------------------
### -- Chunk 2 of 2
```
my $app = route {
    before SomeMiddleware;
    after SomeOtherMiddleware;
    get -> {
        content 'text/plain', 'Hello with middleware';
    }
}
```

Is equivalent to:

```
my $routes = route {
    get -> {
        content 'text/plain', 'Hello with middleware';
    }
}
my $app = Cro.compose(SomeMiddleware, $routes, SomeOtherMiddleware);
```

This is mainly useful when the middleware:

* Might influence what routes match (for example, session and authorization
  middleware)
* Should be executed whether or not any routes from the `route` block match

A `route` block which uses `before` and `after` cannot be used with `include`.
The middleware should run before matching, however before matching it's not
possible to know if one of the included `route`s would match. Use `delegate`
instead.

By contrast, `before-matched` and `after-matched` specify middleware to be
used *only when a route has been matched*. Therefore, it is possible to use
`include` on a `route` block that uses them.

Therefore, the overall process can be seen as:

```
Run any before middleware
If a route matches then
    Run applicable before-matched middleware
    Run the route handler
    Run applicable after-matched middleware
Run any after middleware
```

Both `before` and `before-matched` may be called with any `Cro::Transform` that
consumes a `Cro::HTTP::Request` and produces a `Cro::HTTP::Request`.

Both `after` and `after-matched` may be called with a `Cro::Transform` that
consumes a `Cro::HTTP::Response` and produces a `Cro::HTTP::Response`.

It is allowed to use all of the middleware addition functions multiple times
in a single route block, and the middleware will be added in the order that
it appears. 

As a convenience, the `before`, `before-matched`, `after`, and `after-matched`
functions may be passed a `Block`. This will be invoked with the
`Cro::HTTP::Request` or `Cro::HTTP::Response` object as an argument, and it can
mutate the request or response (the return value of the block is ignored). The
various response helper functions that are available inside of a route handler
are also available, so adding an extra header to the response can be achieved by:

```
after {
    header 'Strict-transport-security', 'max-age=31536000; includeSubDomains'
}
```

In some cases, it is desirable for `before` middleware to itself produce the
response. When using the block form, the `response` symbol and all functions
that aid in producing responses are available. The `before` will be considered
to have produced a response if, after it has run, the `status` of the response
has been set. For example, producing a 403 Forbidden response to all requests
not coming from the loopback interface could be achieved using:

```
before {
    forbidden unless .connection.peer-host eq '127.0.0.1' | '::1';
}
```

A `before` actually inserts two pipeline components: one that runs the block,
and one that outputs any "early" responses produced by the middleware. The
latter component is inserted as if it were introducd by an `after` immediately
after the `before`. This means that any `after` middleware specified prior to
the `before` block making the early response will be skipped over.

```
# WRONG - the first `after` will be skipped over and so never see the 403
# Forbidden
after {
    if .status == 403 && !.has-body {
        content 'text/html', '<h1>Forbidden</h1>';
    }
}
before {
    forbidden unless .request.connection.peer-host eq '127.0.0.1' | '::1';
}

# CORRECT - the `after` is placed after any early response from the `before`
# is inserted into the output pipeline, and so will add the content to the
# response, as desired.
before {
    forbidden unless .request.connection.peer-host eq '127.0.0.1' | '::1';
}
after {
    if .status == 403 && !.has-body {
        content 'text/html', '<h1>Forbidden</h1>';
    }
}
```

When `include` is used, the `before-matched` middleware of the including
`route` block will be applied ahead of any middleware in the target of the
`include`, and the `after-matched` middleware of the including `route` block
will be applied after the target of the include. Effectively, the middleware
of the including route block wraps around those of the included.

## Wrapping route handlers

The `around` function can be used at `route`-block level to wrap all handlers
within that `route` block. This could be used to provide uniform exception
handling across a set of request handlers.

```
my $application = route {
    around -> &handler {
        # Invoke the route handler
        handler();
        CATCH {
            # If any handler produces this exception...
            when Some::Domain::Exception::UpdatingOldVersion {
                # ...return a HTTP 409 Conflict response.
                conflict;
            }
        }
    }
}
```

Both `request` and `response` are available inside of an `around` handler. At
the point it is called, the handler to call and its arguments will already
have been determined. The most you can do is choose not to invoke the handler.
Unlike with `after-matched` middleware, the default mapping of unhandled
exceptions to a `500` status code will not have been performed yet, making it
a good place to factor out mapping of domain exceptions into HTTP errors.

The first `around` call will be the innermost wrapping. Wrappings from an
`include`d `route` block will be considered inner to those in the `route`
block doing the `include`. If one `around` handler throws an exception,
another handler outer to it may catch it. Unlike with middleware, `around`
handlers are not considered pipeline components.


