2019-11-18 05:58:33 +01:00
---
2017-06-23 01:43:19 +02:00
title: HTTP Middlewares
summary: Create objects for modifying request and response objects across controllers.
2019-11-18 05:58:33 +01:00
---
2017-06-23 01:43:19 +02:00
# HTTP Middlewares
2021-02-10 23:25:24 +01:00
HTTP Middlewares allow you to add code that will run before or after a request has been delegated to the router. These might be used for
2021-02-12 03:44:48 +01:00
authentication, logging, caching, request processing, and many other purposes.
2021-02-10 23:33:01 +01:00
[notice]
2021-06-30 11:48:52 +02:00
Note this interface replaces the Silverstripe CMS 3 interface [RequestFilter ](api:SilverStripe\Control\RequestFilter ), which still works but is deprecated.
2021-02-10 23:33:01 +01:00
[/notice]
2017-06-23 01:43:19 +02:00
2017-07-10 00:19:17 +02:00
To create a middleware class, implement `SilverStripe\Control\Middleware\HTTPMiddleware` and define the
`process(HTTPRequest $request, callable $delegate)` method. You can do anything you like in this
2017-06-25 05:12:29 +02:00
method, but to continue normal execution, you should call `$response = $delegate($request)`
at some point in this method.
2017-06-23 01:43:19 +02:00
2017-07-10 00:19:17 +02:00
In addition, you should return an `HTTPResponse` object. In normal cases, this should be the
`$response` object returned by `$delegate` , perhaps with some modification. However, sometimes you
2017-06-23 01:43:19 +02:00
will deliberately return a different response, e.g. an error response or a redirection.
2021-10-07 10:13:26 +02:00
**app/src/CustomMiddleware.php**
2017-06-23 01:43:19 +02:00
2017-07-10 00:19:17 +02:00
```php
2017-11-20 01:10:37 +01:00
use SilverStripe\Control\Middleware\HTTPMiddleware;
2017-07-10 00:19:17 +02:00
use SilverStripe\Control\HTTPRequest;
2017-06-23 01:43:19 +02:00
2017-07-10 00:19:17 +02:00
class CustomMiddleware implements HTTPMiddleware
{
public $Secret = 'SECRET';
2017-06-23 01:43:19 +02:00
2017-07-10 00:19:17 +02:00
public function process(HTTPRequest $request, callable $delegate)
{
// You can break execution by not calling $delegate.
if ($request->getHeader('X-Special-Header') !== $this->Secret) {
return new HTTPResponse('You missed the special header', 400);
}
2017-06-23 01:43:19 +02:00
2019-02-27 02:50:49 +01:00
// You can modify the request before
2017-07-10 00:19:17 +02:00
// For example, this might force JSON responses
$request->addHeader('Accept', 'application/json');
2017-06-23 01:43:19 +02:00
2017-07-10 00:19:17 +02:00
// If you want normal behaviour to occur, make sure you call $delegate($request)
$response = $delegate($request);
2017-06-23 01:43:19 +02:00
2017-07-10 00:19:17 +02:00
// You can modify the response after it has been generated
$response->addHeader('X-Middleware-Applied', 'CustomMiddleware');
2017-06-23 01:43:19 +02:00
2017-07-10 00:19:17 +02:00
// Don't forget to the return the response!
return $response;
}
}
```
2017-06-23 01:43:19 +02:00
2017-07-10 00:19:17 +02:00
Once you have created your middleware class, you must attach it to the `Director` config to make
2017-06-23 01:43:19 +02:00
use of it.
## Global middleware
2017-07-10 00:19:17 +02:00
By adding the service or class name to the `Director.Middlewares` property via injector,
2017-06-25 05:12:29 +02:00
array, a middleware will be executed on every request:
2017-06-23 01:43:19 +02:00
2018-06-25 00:39:53 +02:00
**app/_config/app.yml**
2017-06-23 01:43:19 +02:00
2017-06-25 05:12:29 +02:00
2017-07-10 00:19:17 +02:00
```yaml
---
Name: myrequestprocessors
After:
- requestprocessors
---
SilverStripe\Core\Injector\Injector:
SilverStripe\Control\Director:
properties:
Middlewares:
CustomMiddleware: %$CustomMiddleware
```
2017-06-25 05:12:29 +02:00
2017-06-23 01:43:19 +02:00
Because these are service names, you can configure properties into a custom service if you would
like:
2018-06-25 00:39:53 +02:00
**app/_config/app.yml**
2017-06-23 01:43:19 +02:00
2017-07-10 00:19:17 +02:00
```yaml
SilverStripe\Core\Injector\Injector:
SilverStripe\Control\Director:
properties:
Middlewares:
CustomMiddleware: %$ConfiguredMiddleware
ConfiguredMiddleware:
class: 'CustomMiddleware'
properties:
Secret: "DIFFERENT-ONE"
```
2017-06-23 01:43:19 +02:00
## Route-specific middleware
Alternatively, you can apply middlewares to a specific route. These will be processed after the
2017-06-25 05:12:29 +02:00
global middlewares. You can do this by using the `RequestHandlerMiddlewareAdapter` class
as a replacement for your controller, and register it as a service with a `Middlewares`
property. The controller which does the work should be registered under the
`RequestHandler` property.
2017-06-23 01:43:19 +02:00
2018-06-25 00:39:53 +02:00
**app/_config/app.yml**
2017-06-23 01:43:19 +02:00
2017-07-10 00:19:17 +02:00
```yaml
SilverStripe\Core\Injector\Injector:
SpecialRouteMiddleware:
class: SilverStripe\Control\Middleware\RequestHandlerMiddlewareAdapter
properties:
RequestHandler: %$MyController
Middlewares:
- %$CustomMiddleware
- %$AnotherMiddleware
SilverStripe\Control\Director:
rules:
special\section:
Controller: %$SpecialRouteMiddleware
```
2017-06-23 01:43:19 +02:00
2020-05-07 01:22:32 +02:00
## Application middleware
Some use cases will require a middleware to run before the Silverstripe CMS has been fully bootstrapped (e.g.: Updating
the HTTPRequest before Silverstripe CMS routes it to a controller). This can be achieved by editing the Silverstripe
CMS entry point file.
This file will be located in your own codebase at `public/index.php` , or directly in your project root at `index.php`
if your project doesn't use the public web root. Find the line that instantiate `HTTPApplication` . Call the
`addMiddleware` method on the `HTTPApplication` instance and pass it an instance of your middleware. This must be done
before the request is handled.
```php
// Default application
$kernel = new CoreKernel(BASE_PATH);
$app = new HTTPApplication($kernel);
$app->addMiddleware(new MyApplicationMiddleware());
$response = $app->handle($request);
$response->output();
```
Beware that by this point, the Silverstripe framework features you normally rely on won't be
available in your middleware or in `index.php` because they won't have been initialised yet. (e.g.: ORM, Injector, services configured by Injector)
For example, Silverstripe's autoloading functionality won't work in `index.php` . So you might have to take additional
steps to load your custom middleware class.
[Configuring autoloading in your `composer.json` file ](https://getcomposer.org/doc/04-schema.md#autoload ) is the best
way to achieve this. Remember to call `composer dump-autoload` to regenerate your autoloader.
Alternatively, you can manually include the file containing your custom middleware with a `require` call. e.g.:
`require __DIR__.'/../app/src/MyApplicationMiddleware.php';`
2017-06-23 01:43:19 +02:00
## API Documentation
2020-01-19 19:03:35 +01:00
* [Built-in Middleware ](/developer_guides/controllers/builtin_middlewares )
2017-07-10 00:19:17 +02:00
* [HTTPMiddleware ](api:SilverStripe\Control\Middleware\HTTPMiddleware )