mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
API: Deprecate RequestFilter.
NEW: Allow application of HTTPMiddleware to Director. Director can now use the same HTTPMiddleware objects as the app object. They can be applied either globally or pre-rule.
This commit is contained in:
parent
26b9bf11ed
commit
b30f410ea0
@ -2,6 +2,8 @@
|
|||||||
Name: rootroutes
|
Name: rootroutes
|
||||||
---
|
---
|
||||||
SilverStripe\Control\Director:
|
SilverStripe\Control\Director:
|
||||||
|
middlewares:
|
||||||
|
RequestProcessor: 'SilverStripe\Control\RequestProcessor'
|
||||||
rules:
|
rules:
|
||||||
'': SilverStripe\Control\Controller
|
'': SilverStripe\Control\Controller
|
||||||
---
|
---
|
||||||
|
@ -131,24 +131,12 @@ class Director implements TemplateGlobalProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pre-request
|
|
||||||
$output = RequestProcessor::singleton()->preRequest($request);
|
|
||||||
if ($output === false) {
|
|
||||||
return new HTTPResponse(_t(__CLASS__.'.INVALID_REQUEST', 'Invalid request'), 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate output
|
// Generate output
|
||||||
$result = static::handleRequest($request);
|
$result = static::handleRequest($request);
|
||||||
|
|
||||||
// Save session data. Note that save() will start/resume the session if required.
|
// Save session data. Note that save() will start/resume the session if required.
|
||||||
$request->getSession()->save();
|
$request->getSession()->save();
|
||||||
|
|
||||||
// Post-request handling
|
|
||||||
$postRequest = RequestProcessor::singleton()->postRequest($request, $result);
|
|
||||||
if ($postRequest === false) {
|
|
||||||
return new HTTPResponse(_t(__CLASS__ . '.REQUEST_ABORTED', 'Request aborted'), 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
@ -351,6 +339,14 @@ class Director implements TemplateGlobalProvider
|
|||||||
{
|
{
|
||||||
$rules = Director::config()->uninherited('rules');
|
$rules = Director::config()->uninherited('rules');
|
||||||
|
|
||||||
|
// Get global middlewares
|
||||||
|
$middlewares = Director::config()->uninherited('middlewares') ?: [];
|
||||||
|
|
||||||
|
// Default handler - mo URL rules matched, so return a 404 error.
|
||||||
|
$handler = function () {
|
||||||
|
return new HTTPResponse('No URL rule was matched', 404);
|
||||||
|
};
|
||||||
|
|
||||||
foreach ($rules as $pattern => $controllerOptions) {
|
foreach ($rules as $pattern => $controllerOptions) {
|
||||||
// Normalise route rule
|
// Normalise route rule
|
||||||
if (is_string($controllerOptions)) {
|
if (is_string($controllerOptions)) {
|
||||||
@ -361,6 +357,18 @@ class Director implements TemplateGlobalProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add controller-specific middlewares
|
||||||
|
if (isset($controllerOptions['Middlewares'])) {
|
||||||
|
// Force to array
|
||||||
|
if (!is_array($controllerOptions['Middlewares'])) {
|
||||||
|
$controllerOptions['Middlewares'] = [$controllerOptions['Middlewares']];
|
||||||
|
}
|
||||||
|
$middlewares = array_merge($middlewares, $controllerOptions['Middlewares']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove null middlewares (may be included due to limitatons of config yml)
|
||||||
|
$middlewares = array_filter($middlewares);
|
||||||
|
|
||||||
// Match pattern
|
// Match pattern
|
||||||
$arguments = $request->match($pattern, true);
|
$arguments = $request->match($pattern, true);
|
||||||
if ($arguments !== false) {
|
if ($arguments !== false) {
|
||||||
@ -373,28 +381,71 @@ class Director implements TemplateGlobalProvider
|
|||||||
$request->shift($controllerOptions['_PopTokeniser']);
|
$request->shift($controllerOptions['_PopTokeniser']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle redirection
|
// Handler for redirection
|
||||||
if (isset($arguments['Redirect'])) {
|
if (isset($arguments['Redirect'])) {
|
||||||
// Redirection
|
$handler = function () use ($arguments) {
|
||||||
$response = new HTTPResponse();
|
// Redirection
|
||||||
$response->redirect(static::absoluteURL($arguments['Redirect']));
|
$response = new HTTPResponse();
|
||||||
return $response;
|
$response->redirect(static::absoluteURL($arguments['Redirect']));
|
||||||
|
return $response;
|
||||||
|
};
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the controller name
|
// Find the controller name
|
||||||
$controller = $arguments['Controller'];
|
$controller = $arguments['Controller'];
|
||||||
$controllerObj = Injector::inst()->create($controller);
|
$controllerObj = Injector::inst()->create($controller);
|
||||||
|
|
||||||
try {
|
// Handler for calling a controller
|
||||||
return $controllerObj->handleRequest($request);
|
$handler = function ($request) use ($controllerObj) {
|
||||||
} catch (HTTPResponse_Exception $responseException) {
|
try {
|
||||||
return $responseException->getResponse();
|
return $controllerObj->handleRequest($request);
|
||||||
}
|
} catch (HTTPResponse_Exception $responseException) {
|
||||||
|
return $responseException->getResponse();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No URL rules matched, so return a 404 error.
|
// Call the handler with the given middlewares
|
||||||
return new HTTPResponse('No URL rule was matched', 404);
|
return self::callWithMiddlewares(
|
||||||
|
$request,
|
||||||
|
$middlewares,
|
||||||
|
$handler
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call the given request handler with the given middlewares
|
||||||
|
* Middlewares are specified as Injector service names
|
||||||
|
*
|
||||||
|
* @param $request The request to pass to the handler
|
||||||
|
* @param $middlewareNames The services names of the middlewares to apply
|
||||||
|
* @param $handler The request handler
|
||||||
|
*/
|
||||||
|
protected static function callWithMiddlewares(HTTPRequest $request, array $middlewareNames, callable $handler)
|
||||||
|
{
|
||||||
|
$next = $handler;
|
||||||
|
|
||||||
|
if ($middlewareNames) {
|
||||||
|
$middlewares = array_map(
|
||||||
|
function ($name) {
|
||||||
|
return Injector::inst()->get($name);
|
||||||
|
},
|
||||||
|
$middlewareNames
|
||||||
|
);
|
||||||
|
|
||||||
|
// Reverse middlewares
|
||||||
|
/** @var HTTPMiddleware $middleware */
|
||||||
|
foreach (array_reverse($middlewares) as $middleware) {
|
||||||
|
$next = function ($request) use ($middleware, $next) {
|
||||||
|
return $middleware->process($request, $next);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,11 +3,13 @@
|
|||||||
namespace SilverStripe\Control;
|
namespace SilverStripe\Control;
|
||||||
|
|
||||||
use SilverStripe\Core\Injector\Injectable;
|
use SilverStripe\Core\Injector\Injectable;
|
||||||
|
use SilverStripe\Dev\Deprecation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a request processer that delegates pre and post request handling to nested request filters
|
* Middleware that provides back-support for the deprecated RequestFilter API.
|
||||||
|
* You should use HTTPMiddleware directly instead.
|
||||||
*/
|
*/
|
||||||
class RequestProcessor implements RequestFilter
|
class RequestProcessor implements HTTPMiddleware
|
||||||
{
|
{
|
||||||
use Injectable;
|
use Injectable;
|
||||||
|
|
||||||
@ -33,25 +35,34 @@ class RequestProcessor implements RequestFilter
|
|||||||
$this->filters = $filters;
|
$this->filters = $filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function preRequest(HTTPRequest $request)
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function process(HTTPRequest $request, callable $delegate)
|
||||||
{
|
{
|
||||||
|
if ($this->filters) {
|
||||||
|
Deprecation::notice(
|
||||||
|
'4.0',
|
||||||
|
'Deprecated RequestFilters are in use. Apply HTTPMiddleware to Director.middlewares instead.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($this->filters as $filter) {
|
foreach ($this->filters as $filter) {
|
||||||
$res = $filter->preRequest($request);
|
$res = $filter->preRequest($request);
|
||||||
if ($res === false) {
|
if ($res === false) {
|
||||||
return false;
|
return new HTTPResponse(_t(__CLASS__.'.INVALID_REQUEST', 'Invalid request'), 400);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function postRequest(HTTPRequest $request, HTTPResponse $response)
|
$response = $delegate($request);
|
||||||
{
|
|
||||||
foreach ($this->filters as $filter) {
|
foreach ($this->filters as $filter) {
|
||||||
$res = $filter->postRequest($request, $response);
|
$res = $filter->postRequest($request, $response);
|
||||||
if ($res === false) {
|
if ($res === false) {
|
||||||
return false;
|
return new HTTPResponse(_t(__CLASS__ . '.REQUEST_ABORTED', 'Request aborted'), 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user