Add safeguard against infinite routing loops
This commit is contained in:
parent
6013198436
commit
d91ac12541
|
|
@ -1,3 +1,9 @@
|
|||
### v1.3.0
|
||||
- Allow Routers to dispatch additional Routers.
|
||||
|
||||
### v1.2.2
|
||||
- Fix issue with 100 Continue status codes, etc. where r\n\r\n appears within the list of headers
|
||||
|
||||
### v1.2.1
|
||||
- Allow Request to read request headers without apache_request_headers().
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
namespace pjdietz\WellRESTed;
|
||||
|
||||
use pjdietz\WellRESTed\Interfaces\HandlerInterface;
|
||||
use pjdietz\WellRESTed\Interfaces\RequestInterface;
|
||||
use pjdietz\WellRESTed\Interfaces\ResponseInterface;
|
||||
use pjdietz\WellRESTed\Interfaces\RouteInterface;
|
||||
|
|
@ -26,8 +25,14 @@ class Router extends RouteTarget implements RouterInterface
|
|||
{
|
||||
/** @var string Fully qualified name for the interface for handlers */
|
||||
const ROUTE_TARGET_INTERFACE = '\\pjdietz\\WellRESTed\\Interfaces\\RouteTargetInterface';
|
||||
/** @var int Default maximum number of levels of routing. */
|
||||
const MAX_DEPTH = 10;
|
||||
/** @var int maximum levels of routing before the router raises an error. */
|
||||
protected $maxDepth = self::MAX_DEPTH;
|
||||
/** @var array Array of Route objects */
|
||||
private $routes;
|
||||
/** @var int counter incrememted each time a router dispatches a route target. */
|
||||
private $depth = 0;
|
||||
|
||||
/** Create a new Router. */
|
||||
public function __construct()
|
||||
|
|
@ -53,10 +58,16 @@ class Router extends RouteTarget implements RouterInterface
|
|||
*/
|
||||
public function getResponse(RequestInterface $request = null)
|
||||
{
|
||||
if (is_null($request)) {
|
||||
$request = Request::getRequest();
|
||||
// Set the instance's request, if the called passed one.
|
||||
if (!is_null($request)) {
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
// If the instance does not have a request, use the singleton.
|
||||
if (is_null($this->request)) {
|
||||
$this->request = Request::getRequest();
|
||||
}
|
||||
// Reference the request and path.
|
||||
$request = $this->request;
|
||||
$path = $request->getPath();
|
||||
|
||||
foreach ($this->routes as $route) {
|
||||
|
|
@ -79,8 +90,10 @@ class Router extends RouteTarget implements RouterInterface
|
|||
// If this instance already had a top-level router, pass it along.
|
||||
// Otherwise, pass itself as the top-level router.
|
||||
if (isset($this->router)) {
|
||||
$this->router->incrementDepth();
|
||||
$target->setRouter($this->router);
|
||||
} else {
|
||||
$this->incrementDepth();
|
||||
$target->setRouter($this);
|
||||
}
|
||||
|
||||
|
|
@ -95,6 +108,19 @@ class Router extends RouteTarget implements RouterInterface
|
|||
return $this->getNoRouteResponse($request);
|
||||
}
|
||||
|
||||
public function incrementDepth()
|
||||
{
|
||||
$this->depth++;
|
||||
if ($this->depth >= $this->maxDepth) {
|
||||
$response = $this->getInternalServerErrorResponse(
|
||||
$this->getRequest(),
|
||||
'Maximum recursion level reached.'
|
||||
);
|
||||
$response->respond();
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a resonse indicating a 404 Not Found error
|
||||
*
|
||||
|
|
@ -109,10 +135,10 @@ class Router extends RouteTarget implements RouterInterface
|
|||
}
|
||||
|
||||
/** Prepare a response indicating a 500 Internal Server Error */
|
||||
protected function getInternalServerErrorResponse(RequestInterface $request)
|
||||
protected function getInternalServerErrorResponse(RequestInterface $request, $message = '')
|
||||
{
|
||||
$response = new Response(500);
|
||||
$response->body = 'Server error at ' . $request->getPath();
|
||||
$response->setBody('Server error at ' . $request->getPath() . "\n" . $message);
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue