Middleware is logic that is run before and after each request and is modelled after Django’s Middleware system. It offers the following hooks:
To generate your own middleware, simply inherit from the Middleware class and overwrite the methods that should be used.
<?php
namespace OCA\MyApp\Middleware;
use \OCP\AppFramework\Middleware;
class CensorMiddleware extends Middleware {
/**
* this replaces "bad words" with "********" in the output
*/
public function beforeOutput($controller, $methodName, $output){
return str_replace('bad words', '********', $output);
}
}
The middleware can be registered in the Container and added using the registerMiddleware method:
<?php
namespace OCA\MyApp\AppInfo;
use \OCP\AppFramework\App;
use \OCA\MyApp\Middleware\CensorMiddleware;
class MyApp extends App {
/**
* Define your dependencies in here
*/
public function __construct(array $urlParams=array()){
parent::__construct('myapp', $urlParams);
$container = $this->getContainer();
/**
* Middleware
*/
$container->registerService('CensorMiddleware', function($c){
return new CensorMiddleware();
});
// executed in the order that it is registered
$container->registerMiddleware('CensorMiddleware');
}
}
Note
The order is important! The middleware that is registered first gets run first in the beforeController method. For all other hooks, the order is being reversed, meaning: if a middleware is registered first, it gets run last.
Sometimes its useful to conditionally execute code before or after a controller method. This can be done by defining custom annotations. An example would be to add a custom authentication method or simply add an additional header to the response. To access the parsed annotations, inject the ControllerMethodReflector class:
<?php
namespace OCA\MyApp\Middleware;
use \OCP\AppFramework\Middleware;
use \OCP\AppFramework\Utility\ControllerMethodReflector;
use \OCP\IRequest;
class HeaderMiddleware extends Middleware {
private $reflector;
public function __construct(ControllerMethodReflector $reflector) {
$this->reflector = $reflector;
}
/**
* Add custom header if @MyHeader is used
*/
public function afterController($controller, $methodName, IResponse $response){
if($this->reflector->hasAnnotation('MyHeader')) {
$response->addHeader('My-Header', 3);
}
return $response;
}
}
Now adjust the container to inject the reflector:
<?php
namespace OCA\MyApp\AppInfo;
use \OCP\AppFramework\App;
use \OCA\MyApp\Middleware\HeaderMiddleware;
class MyApp extends App {
/**
* Define your dependencies in here
*/
public function __construct(array $urlParams=array()){
parent::__construct('myapp', $urlParams);
$container = $this->getContainer();
/**
* Middleware
*/
$container->registerService('HeaderMiddleware', function($c){
return new HeaderMiddleware($c->query('ControllerMethodReflector'));
});
// executed in the order that it is registered
$container->registerMiddleware('HeaderMiddleware');
}
}
Note
An annotation always starts with an uppercase letter