Compare commits

...

13 Commits

Author SHA1 Message Date
Simon Sessingø 0dbc4e6ba2 Merge pull request #376 from skipperbent/v3-development
Optimisations
2018-02-27 00:20:12 +01:00
Simon Sessingo 6d7d07669b Optimisations 2018-02-27 00:19:44 +01:00
Simon Sessingø a4dfa59a66 Merge pull request #374 from skipperbent/v3-development
Stop router from processing routes if no valid route is found.
2018-02-27 00:14:24 +01:00
Simon Sessingo 98bf95bfc9 Added back getPath. 2018-02-27 00:14:01 +01:00
Simon Sessingo b051bcf02b Stop router from processing routes if no valid route is found. 2018-02-27 00:12:45 +01:00
Simon Sessingo b8d5106f4e Removed getPath from url. 2018-02-27 00:00:54 +01:00
Simon Sessingø 2c9d996437 Merge pull request #372 from skipperbent/v3-development
Fixed setUrl issue.
2018-02-26 23:48:45 +01:00
Simon Sessingo cfc9ac138a Fixed setUrl issue. 2018-02-26 23:48:09 +01:00
Simon Sessingø 98ce5f7635 Merge pull request #370 from skipperbent/v3-development
Development
2018-02-26 23:24:37 +01:00
Simon Sessingo a25be983b8 Development
- Renamed Uri class to Url.
- Renamed setUri and getUri to setUrl and getUrl.
- Added custom Exceptions and ensured that router only throws HttpExceptions.
- Added isAjax method to Request class.
- Added better phpDocs.
- Other minor optimisations.
2018-02-26 23:21:26 +01:00
Simon Sessingø 69bb570c73 Merge pull request #368 from skipperbent/v3-development
Version 3.5.0.0
2018-02-24 05:39:20 +01:00
Simon Sessingø a0c5bbdcc0 Merge pull request #367 from skipperbent/v3-rewrite-update
Simplified url-rewriting and callback handling.
2018-02-24 05:36:37 +01:00
Simon Sessingo 50c6499efb Simplified url-rewriting and callback handling. 2018-02-24 05:35:05 +01:00
19 changed files with 391 additions and 241 deletions
+9 -117
View File
@@ -600,7 +600,7 @@ SimpleRouter::group(['namespace' => 'Admin'], function () {
### Sub domain-routing
Route groups may also be used to handle sub-domain routing. Sub-domains may be assigned route parameters just like route URIs, allowing you to capture a portion of the sub-domain for usage in your route or controller. The sub-domain may be specified using the `domain` key on the group attribute array:
Route groups may also be used to handle sub-domain routing. Sub-domains may be assigned route parameters just like route urls, allowing you to capture a portion of the sub-domain for usage in your route or controller. The sub-domain may be specified using the `domain` key on the group attribute array:
```php
SimpleRouter::group(['domain' => '{account}.myapp.com'], function () {
@@ -612,7 +612,7 @@ SimpleRouter::group(['domain' => '{account}.myapp.com'], function () {
### Route prefixes
The `prefix` group attribute may be used to prefix each route in the group with a given URI. For example, you may want to prefix all route URIs within the group with `admin`:
The `prefix` group attribute may be used to prefix each route in the group with a given url. For example, you may want to prefix all route urls within the group with `admin`:
```php
SimpleRouter::group(['prefix' => '/admin'], function () {
@@ -894,7 +894,7 @@ class CustomExceptionHandler implements IExceptionHandler
/* You can use the exception handler to format errors depending on the request and type. */
if (stripos($request->getUri()->getPath(), '/api') !== false) {
if (stripos($request->getUrl()->getPath(), '/api') !== false) {
response()->json([
'error' => $error->getMessage(),
@@ -1136,125 +1136,18 @@ $siteId = input('site_id', 2, ['post', 'get']);
## Url rewriting
Sometimes it can be useful to manipulate the route about to be loaded.
simple-php-router allows you to easily change the route about to be executed.
simple-php-router allows you to easily manipulate and change the routes which are about to be rendered.
All information about the current route is stored in the `\Pecee\SimpleRouter\Router` instance's `loadedRoute` property.
For easy access you can use the shortcut method `\Pecee\SimpleRouter\SimpleRouter::router()`.
For easy access you can use the shortcut helper function `request()` instead of calling the class directly `\Pecee\SimpleRouter\SimpleRouter::router()`.
```php
use Pecee\SimpleRouter;
$request = SimpleRouter::request();
$request->setRewriteCallback('Example\MyCustomClass@hello');
request()->setRewriteCallback('Example\MyCustomClass@hello');
// -- or you can rewrite by url --
$request->setRewriteUrl('/my-rewrite-url');
```
**Note:** It's only possible to change the route BEFORE the route has initially been rendered. You can use the `Request` object to manipulate the route which are about to be loaded.
### Rewrite using callback
This method is most efficient, as it will render the route immediately.
This method is useful for rendering 404-pages etc.
You can also change the callback by modifying the `$route` parameter. This is perfect if you just want to display a view quickly - or change the callback depending
on some criteria's for the request.
The callback below will fire immediately after the `Middleware` or `ExceptionHandler` has been loaded, as they are loaded before the route is rendered.
If you wish to change the callback from outside, please have this in mind.
The example below will render `DefaultController@notFound` regardless of the url.
**NOTE: Use this method if you want to load another controller. No additional middlewares or rules will be loaded.**
##### Middleware example
```php
namespace Demo\Middlewares;
use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request;
class CustomMiddleware implements IMiddleware {
public function handle(Request $request) {
$request->setRewriteCallback('Demo\Controllers\DefaultController@notFound');
return $request;
}
}
```
##### Exception handler example
```php
namespace Demo\Handlers;
use Pecee\Handlers\IExceptionHandler;
use Pecee\Http\Request;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
class CustomExceptionHandler implements IExceptionHandler
{
public function handleError(Request $request, \Exception $error)
{
/* The router will throw the NotFoundHttpException on 404 */
if($error instanceof NotFoundHttpException) {
/*
* Render your own custom 404-view, rewrite the request to another route,
* or simply return the $request object to ignore the error and continue on rendering the route.
*
* The code below will make the router render our page.notfound route.
*/
$request->setRewriteCallback('Demo\Controllers\DefaultController@notFound');
return $request;
}
throw $error;
}
}
```
### Rewrite using url
The example below will cause the router to reload the request and reinitialize all the routes. This method is slower, but will ensure that all middlewares and rules for the route is loaded.
This method is useful if you want to redirect a url to another-url which is dependent on a middleware. You can also add a custom rule by calling `$request->setRewriteRoute($route)` if
you want to customize request-methods or use another route-type like `RouteController` etc.
We are using the `url()` helper function to get the uri to another route added in the `routes.php` file.
**NOTE: Use this method if you want to fully load another route using it's settings (request method, middlewares etc).**
##### Middleware example
The example below will redirect the request to the `home`-route.
```php
namespace Demo\Middlewares;
use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request;
class CustomMiddleware implements IMiddleware {
public function handle(Request $request) {
$request->setRewriteUrl(url('home'));
return $request;
}
}
request()->setRewriteUrl('/my-rewrite-url');
```
### Bootmanager: loading routes dynamically
@@ -1278,11 +1171,10 @@ class CustomRouterRules implement IRouterBootManager {
foreach($rewriteRules as $url => $rule) {
// If the current uri matches the url, we use our custom route
// If the current url matches the rewrite url, we use our custom route
if($request->getUri()->getPath() === $url) {
if($request->getUrl()->getPath() === $url) {
$request->setRewriteUrl($rule);
return $request;
}
}
@@ -0,0 +1,6 @@
<?php
namespace Pecee\Exceptions;
class InvalidArgumentException extends \InvalidArgumentException {
}
@@ -0,0 +1,8 @@
<?php
namespace Pecee\Http\Exceptions;
class MalformedUrlException extends \Exception
{
}
+36 -14
View File
@@ -2,6 +2,7 @@
namespace Pecee\Http\Input;
use Pecee\Exceptions\InvalidArgumentException;
use Pecee\Http\Request;
class Input
@@ -26,6 +27,10 @@ class Input
*/
protected $request;
/**
* Input constructor.
* @param Request $request
*/
public function __construct(Request $request)
{
$this->request = $request;
@@ -33,6 +38,10 @@ class Input
$this->parseInputs();
}
/**
* Parse input values
*
*/
public function parseInputs()
{
/* Parse get requests */
@@ -57,6 +66,9 @@ class Input
}
}
/**
* @return array
*/
public function parseFiles()
{
$list = [];
@@ -66,7 +78,11 @@ class Input
// Handle array input
if (is_array($value['name']) === false) {
$values['index'] = $key;
$list[$key] = InputFile::createFromArray($values + $value);
try {
$list[$key] = InputFile::createFromArray($values + $value);
} catch(InvalidArgumentException $e ){
}
continue;
}
@@ -97,22 +113,28 @@ class Input
if (is_array($original['name'][$key]) === false) {
$file = InputFile::createFromArray([
'index' => (empty($key) === true && empty($originalIndex) === false) ? $originalIndex : $key,
'name' => $original['name'][$key],
'error' => $original['error'][$key],
'tmp_name' => $original['tmp_name'][$key],
'type' => $original['type'][$key],
'size' => $original['size'][$key],
]);
try {
if (isset($output[$key]) === true) {
$output[$key][] = $file;
$file = InputFile::createFromArray([
'index' => (empty($key) === true && empty($originalIndex) === false) ? $originalIndex : $key,
'name' => $original['name'][$key],
'error' => $original['error'][$key],
'tmp_name' => $original['tmp_name'][$key],
'type' => $original['type'][$key],
'size' => $original['size'][$key],
]);
if (isset($output[$key]) === true) {
$output[$key][] = $file;
continue;
}
$output[$key] = $file;
continue;
}
$output[$key] = $file;
continue;
} catch(InvalidArgumentException $e) {
}
}
$index[] = $key;
+4 -2
View File
@@ -2,6 +2,8 @@
namespace Pecee\Http\Input;
use Pecee\Exceptions\InvalidArgumentException;
class InputFile implements IInputItem
{
public $index;
@@ -26,13 +28,13 @@ class InputFile implements IInputItem
* Create from array
*
* @param array $values
* @throws \InvalidArgumentException
* @throws InvalidArgumentException
* @return static
*/
public static function createFromArray(array $values)
{
if (isset($values['index']) === false) {
throw new \InvalidArgumentException('Index key is required');
throw new InvalidArgumentException('Index key is required');
}
/* Easy way of ensuring that all indexes-are set and not filling the screen with isset() */
@@ -15,6 +15,10 @@ class BaseCsrfVerifier implements IMiddleware
protected $except;
protected $tokenProvider;
/**
* BaseCsrfVerifier constructor.
* @throws \Pecee\Http\Security\Exceptions\SecurityException
*/
public function __construct()
{
$this->tokenProvider = new CookieTokenProvider();
@@ -39,9 +43,9 @@ class BaseCsrfVerifier implements IMiddleware
$url = rtrim($url, '/');
if ($url[strlen($url) - 1] === '*') {
$url = rtrim($url, '*');
$skip = (stripos($request->getUri()->getPath(), $url) === 0);
$skip = (stripos($request->getUrl()->getOriginalUrl(), $url) === 0);
} else {
$skip = ($url === $request->getUri()->getPath());
$skip = ($url === $request->getUrl()->getOriginalUrl());
}
if ($skip === true) {
+48 -14
View File
@@ -12,10 +12,12 @@ class Request
private $data = [];
protected $headers;
protected $host;
protected $uri;
protected $url;
protected $method;
protected $input;
protected $hasRewrite = false;
/**
* @var ILoadableRoute|null
*/
@@ -27,13 +29,17 @@ class Request
*/
protected $loadedRoute;
/**
* Request constructor.
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public function __construct()
{
$this->parseHeaders();
$this->setHost($this->getHeader('http-host'));
// Check if special IIS header exist, otherwise use default.
$this->setUri(new Uri($this->getHeader('unencoded-url', $this->getHeader('request-uri'))));
$this->setUrl($this->getHeader('unencoded-url', $this->getHeader('request-uri')));
$this->input = new Input($this);
$this->method = strtolower($this->input->get('_method', $this->getHeader('request-method')));
@@ -56,11 +62,11 @@ class Request
}
/**
* @return Uri
* @return Url
*/
public function getUri()
public function getUrl()
{
return $this->uri;
return $this->url;
}
/**
@@ -186,6 +192,16 @@ class Request
return ($this->getHeader('http-accept') !== null && stripos($this->getHeader('http-accept'), $format) > -1);
}
/**
* Returns true if the request is made through Ajax
*
* @return bool
*/
public function isAjax()
{
return (strtolower($this->getHeader('http-x-requested-with')) === 'xmlhttprequest');
}
/**
* Get accept formats
* @return array
@@ -196,15 +212,12 @@ class Request
}
/**
* @param Uri|string $uri
* @param string|Url $url
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public function setUri($uri)
public function setUrl($url)
{
if (is_string($uri) === true) {
$uri = new Uri($uri);
}
$this->uri = $uri;
$this->url = ($url instanceof Url) ? $url : new Url($url);
}
/**
@@ -231,6 +244,7 @@ class Request
*/
public function setRewriteRoute(ILoadableRoute $route)
{
$this->hasRewrite = true;
$this->rewriteRoute = SimpleRouter::addDefaultNamespace($route);
return $this;
@@ -264,7 +278,8 @@ class Request
*/
public function setRewriteUrl($rewriteUrl)
{
$this->rewriteUrl = $rewriteUrl;
$this->hasRewrite = true;
$this->rewriteUrl = rtrim($rewriteUrl, '/') . '/';
return $this;
}
@@ -276,7 +291,9 @@ class Request
*/
public function setRewriteCallback($callback)
{
return $this->setRewriteRoute(new RouteUrl($this->uri, $callback));
$this->hasRewrite = true;
return $this->setRewriteRoute(new RouteUrl($this->getUrl()->getPath(), $callback));
}
/**
@@ -301,6 +318,23 @@ class Request
return $this;
}
public function hasRewrite()
{
return $this->hasRewrite;
}
public function setHasRewrite($value)
{
$this->hasRewrite = $value;
return $this;
}
public function isRewrite($url)
{
return ($this->rewriteUrl === $url);
}
public function __isset($name)
{
return array_key_exists($name, $this->data);
+5 -3
View File
@@ -2,6 +2,8 @@
namespace Pecee\Http;
use Pecee\Exceptions\InvalidArgumentException;
class Response
{
protected $request;
@@ -42,7 +44,7 @@ class Response
public function refresh()
{
$this->redirect($this->request->getUri()->getOriginalUrl());
$this->redirect($this->request->getUrl()->getOriginalUrl());
}
/**
@@ -87,12 +89,12 @@ class Response
* @param array|\JsonSerializable $value
* @param int $options JSON options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT, JSON_PRESERVE_ZERO_FRACTION, JSON_UNESCAPED_UNICODE, JSON_PARTIAL_OUTPUT_ON_ERROR.
* @param int $dept JSON debt.
* @throws \InvalidArgumentException
* @throws InvalidArgumentException
*/
public function json($value, $options = null, $dept = 512)
{
if (($value instanceof \JsonSerializable) === false && is_array($value) === false) {
throw new \InvalidArgumentException('Invalid type for parameter "value". Must be of type array or object implementing the \JsonSerializable interface.');
throw new InvalidArgumentException('Invalid type for parameter "value". Must be of type array or object implementing the \JsonSerializable interface.');
}
$this->header('Content-Type: application/json; charset=utf-8');
@@ -2,6 +2,8 @@
namespace Pecee\Http\Security;
use Pecee\Http\Security\Exceptions\SecurityException;
class CookieTokenProvider implements ITokenProvider
{
const CSRF_KEY = 'CSRF-TOKEN';
@@ -9,6 +11,10 @@ class CookieTokenProvider implements ITokenProvider
protected $token;
protected $cookieTimeoutMinutes = 120;
/**
* CookieTokenProvider constructor.
* @throws SecurityException
*/
public function __construct()
{
$this->token = $this->getToken();
@@ -21,20 +27,24 @@ class CookieTokenProvider implements ITokenProvider
/**
* Generate random identifier for CSRF token
*
* @throws \RuntimeException|\Exception
* @return string
* @throws SecurityException
*/
public function generateToken()
{
if (function_exists('random_bytes') === true) {
return bin2hex(random_bytes(32));
try {
return bin2hex(random_bytes(32));
} catch(\Exception $e) {
throw new SecurityException($e->getMessage(), $e->getCode(), $e->getPrevious());
}
}
$isSourceStrong = false;
$random = openssl_random_pseudo_bytes(32, $isSourceStrong);
if ($isSourceStrong === false || $random === false) {
throw new \RuntimeException('IV generation failed');
throw new SecurityException('IV generation failed');
}
return $random;
@@ -0,0 +1,6 @@
<?php
namespace Pecee\Http\Security\Exceptions;
class SecurityException extends \Exception {
}
@@ -2,7 +2,9 @@
namespace Pecee\Http;
class Uri
use Pecee\Http\Exceptions\MalformedUrlException;
class Url
{
private $originalUrl;
private $data = [
@@ -16,6 +18,11 @@ class Uri
'fragment' => null,
];
/**
* Url constructor.
* @param string $url
* @throws MalformedUrlException
*/
public function __construct($url)
{
$this->originalUrl = $url;
@@ -129,7 +136,7 @@ class Uri
* UTF-8 aware parse_url() replacement.
* @param string $url
* @param int $component
* @throws \InvalidArgumentException
* @throws MalformedUrlException
* @return array
*/
public function parseUrl($url, $component = -1)
@@ -145,7 +152,7 @@ class Uri
$parts = parse_url($encodedUrl, $component);
if ($parts === false) {
throw new \InvalidArgumentException('Malformed URL: ' . $url);
throw new MalformedUrlException('Malformed URL: ' . $url);
}
return array_map('urldecode', $parts);
+14 -15
View File
@@ -128,7 +128,7 @@ abstract class Route implements IRoute
// Ensures that hostnames/domains will work with parameters
$url = '/' . ltrim($url, '/');
if (preg_match_all('/' . $regex . '/u', $route, $parameters) > 0) {
if (preg_match_all('/' . $regex . '/u', $route, $parameters) !== 0) {
$urlParts = preg_split('/((\-?\/?)\{[^}]+\})/', $route);
@@ -166,22 +166,21 @@ abstract class Route implements IRoute
$urlRegex = preg_quote($route, '/');
}
if (preg_match(sprintf($this->urlRegex, $urlRegex), $url, $matches) > 0) {
$values = [];
if (isset($parameters[1]) === true) {
/* Only take matched parameters with name */
foreach ((array)$parameters[1] as $name) {
$values[$name] = (isset($matches[$name]) && $matches[$name] !== '') ? $matches[$name] : null;
}
}
return $values;
if (preg_match(sprintf($this->urlRegex, $urlRegex), $url, $matches) === 0) {
return null;
}
return null;
$values = [];
if (isset($parameters[1]) === true) {
/* Only take matched parameters with name */
foreach ((array)$parameters[1] as $name) {
$values[$name] = (isset($matches[$name]) && $matches[$name] !== '') ? $matches[$name] : null;
}
}
return $values;
}
/**
+67 -45
View File
@@ -2,6 +2,7 @@
namespace Pecee\SimpleRouter;
use Pecee\Exceptions\InvalidArgumentException;
use Pecee\Handlers\IExceptionHandler;
use Pecee\Http\Middleware\BaseCsrfVerifier;
use Pecee\Http\Request;
@@ -65,11 +66,18 @@ class Router
*/
protected $exceptionHandlers;
/**
* Router constructor.
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public function __construct()
{
$this->reset();
}
/**
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public function reset()
{
$this->processingRoute = false;
@@ -116,7 +124,7 @@ class Router
$exceptionHandlers = [];
$url = ($this->request->getRewriteUrl() !== null) ? $this->request->getRewriteUrl() : $this->request->getUri()->getPath();
$url = ($this->request->getRewriteUrl() !== null) ? $this->request->getRewriteUrl() : $this->request->getUrl()->getPath();
foreach ($routes as $route) {
@@ -192,6 +200,11 @@ class Router
*/
public function loadRoutes()
{
// Stop processing routes if no valid route is found.
if($this->request->getRewriteRoute() === null && $this->request->getUrl() === null) {
return;
}
/* Initialize boot-managers */
/* @var $manager IRouterBootManager */
foreach ($this->bootManagers as $manager) {
@@ -208,7 +221,6 @@ class Router
* @param bool $rewrite
* @return string|mixed
* @throws HttpException
* @throws \Exception
*/
public function routeRequest($rewrite = false)
{
@@ -224,14 +236,15 @@ class Router
/* Verify csrf token for request */
$this->csrfVerifier->handle($this->request);
}
} else {
$this->request->setHasRewrite(false);
}
$url = ($this->request->getRewriteUrl() !== null) ? $this->request->getRewriteUrl() : $this->request->getUri()->getPath();
$url = ($this->request->getRewriteUrl() !== null) ? $this->request->getRewriteUrl() : $this->request->getUrl()->getPath();
/* @var $route ILoadableRoute */
foreach ($this->processedRoutes as $key => $route) {
/* If the route matches */
if ($route->matchRoute($url, $this->request) === true) {
@@ -243,29 +256,28 @@ class Router
$route->loadMiddleware($this->request);
$rewriteRoute = $this->request->getRewriteRoute();
if ($rewriteRoute !== null) {
$rewriteRoute->loadMiddleware($this->request);
return $rewriteRoute->renderRoute($this->request);
}
/* If the request has changed */
$rewriteUrl = $this->request->getRewriteUrl();
if ($rewriteUrl !== null && $rewriteUrl !== $url) {
if ($this->hasRewrite($url) === true) {
unset($this->processedRoutes[$key]);
$this->processedRoutes = array_values($this->processedRoutes);
return $this->routeRequest(true);
}
/* Render route */
$routeNotAllowed = false;
$this->request->setLoadedRoute($route);
return $route->renderRoute($this->request);
$output = $route->renderRoute($this->request);
if ($output !== null) {
return $output;
}
if ($this->hasRewrite($url) === true) {
unset($this->processedRoutes[$key]);
return $this->routeRequest(true);
}
}
}
@@ -274,7 +286,7 @@ class Router
}
if ($routeNotAllowed === true) {
$message = sprintf('Route "%s" or method "%s" not allowed.', $this->request->getUri()->getPath(), $this->request->getMethod());
$message = sprintf('Route "%s" or method "%s" not allowed.', $this->request->getUrl()->getPath(), $this->request->getMethod());
$this->handleException(new HttpException($message, 403));
}
@@ -283,9 +295,9 @@ class Router
$rewriteUrl = $this->request->getRewriteUrl();
if ($rewriteUrl !== null) {
$message = sprintf('Route not found: "%s" (rewrite from: "%s")', $rewriteUrl, $this->request->getUri()->getPath());
$message = sprintf('Route not found: "%s" (rewrite from: "%s")', $rewriteUrl, $this->request->getUrl()->getPath());
} else {
$message = sprintf('Route not found: "%s"', $this->request->getUri()->getPath());
$message = sprintf('Route not found: "%s"', $this->request->getUrl()->getPath());
}
$this->handleException(new NotFoundHttpException($message, 404));
@@ -294,16 +306,38 @@ class Router
return null;
}
protected function hasRewrite($url)
{
/* If the request has changed */
if ($this->request->hasRewrite() === true) {
if ($this->request->getRewriteRoute() !== null) {
/* Render rewrite-route */
$this->processedRoutes[] = $this->request->getRewriteRoute();
return true;
}
if ($this->request->isRewrite($url) === false) {
/* Render rewrite-url */
$this->processedRoutes = array_values($this->processedRoutes);
return true;
}
}
return false;
}
/**
* @param \Exception $e
* @throws HttpException
* @throws \Exception
* @return string
*/
protected function handleException(\Exception $e)
{
$url = ($this->request->getRewriteUrl() !== null) ? $this->request->getRewriteUrl() : $this->request->getUri()->getPath();
/* @var $handler IExceptionHandler */
foreach ($this->exceptionHandlers as $key => $handler) {
@@ -317,25 +351,13 @@ class Router
try {
if ($handler->handleError($this->request, $e) !== null) {
$handler->handleError($this->request, $e);
$rewriteRoute = $this->request->getRewriteRoute();
if ($this->request->hasRewrite() === true) {
unset($this->exceptionHandlers[$key]);
$this->exceptionHandlers = array_values($this->exceptionHandlers);
if ($rewriteRoute !== null) {
$rewriteRoute->loadMiddleware($this->request);
return $rewriteRoute->renderRoute($this->request);
}
$rewriteUrl = $this->request->getRewriteUrl();
/* If the request has changed */
if ($rewriteUrl !== null && $rewriteUrl !== $url) {
unset($this->exceptionHandlers[$key]);
$this->exceptionHandlers = array_values($this->exceptionHandlers);
return $this->routeRequest(true);
}
return $this->routeRequest(true);
}
} catch (\Exception $e) {
@@ -343,7 +365,7 @@ class Router
}
}
throw $e;
throw new HttpException($e->getMessage(), $e->getCode(), $e->getPrevious());
}
public function arrayToParams(array $getParams = [], $includeEmpty = true)
@@ -425,13 +447,13 @@ class Router
* @param string|null $name
* @param string|array|null $parameters
* @param array|null $getParams
* @throws \InvalidArgumentException
* @throws InvalidArgumentException
* @return string
*/
public function getUrl($name = null, $parameters = null, $getParams = null)
{
if ($getParams !== null && is_array($getParams) === false) {
throw new \InvalidArgumentException('Invalid type for getParams. Must be array or null');
throw new InvalidArgumentException('Invalid type for getParams. Must be array or null');
}
if ($name === '' && $parameters === '') {
@@ -447,7 +469,7 @@ class Router
/* Return current route if no options has been specified */
if ($name === null && $parameters === null) {
return $this->request->getUri()->getPath() . $this->arrayToParams($getParams);
return $this->request->getUrl()->getPath() . $this->arrayToParams($getParams);
}
$loadedRoute = $this->request->getLoadedRoute();
+31 -10
View File
@@ -10,11 +10,11 @@
namespace Pecee\SimpleRouter;
use Pecee\Exceptions\InvalidArgumentException;
use Pecee\Handlers\CallbackExceptionHandler;
use Pecee\Http\Middleware\BaseCsrfVerifier;
use Pecee\Http\Response;
use Pecee\SimpleRouter\Exceptions\HttpException;
use Pecee\SimpleRouter\Exceptions\NotFoundHttpException;
use Pecee\SimpleRouter\Route\IRoute;
use Pecee\SimpleRouter\Route\RoutePartialGroup;
use Pecee\SimpleRouter\Route\RouteController;
@@ -43,9 +43,8 @@ class SimpleRouter
protected static $router;
/**
* Start/route request
*
* @throws HttpException|NotFoundHttpException|\Exception
* @throws \Pecee\Http\Exceptions\MalformedUrlException
* @throws HttpException
*/
public static function start()
{
@@ -66,6 +65,7 @@ class SimpleRouter
* Base CSRF verifier
*
* @param BaseCsrfVerifier $baseCsrfVerifier
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function csrfVerifier(BaseCsrfVerifier $baseCsrfVerifier)
{
@@ -77,6 +77,7 @@ class SimpleRouter
* Perfect if you want to load pretty-urls from a file or database.
*
* @param IRouterBootManager $bootManager
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function addBootManager(IRouterBootManager $bootManager)
{
@@ -89,7 +90,9 @@ class SimpleRouter
* @param string $url
* @param string|\Closure $callback
* @param array|null $settings
*
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function get($url, $callback, array $settings = null)
{
@@ -103,6 +106,7 @@ class SimpleRouter
* @param string|\Closure $callback
* @param array|null $settings
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function post($url, $callback, array $settings = null)
{
@@ -116,6 +120,7 @@ class SimpleRouter
* @param string|\Closure $callback
* @param array|null $settings
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function put($url, $callback, array $settings = null)
{
@@ -129,6 +134,7 @@ class SimpleRouter
* @param string|\Closure $callback
* @param array|null $settings
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function patch($url, $callback, array $settings = null)
{
@@ -142,6 +148,7 @@ class SimpleRouter
* @param string|\Closure $callback
* @param array|null $settings
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function options($url, $callback, array $settings = null)
{
@@ -155,6 +162,7 @@ class SimpleRouter
* @param string|\Closure $callback
* @param array|null $settings
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function delete($url, $callback, array $settings = null)
{
@@ -166,13 +174,14 @@ class SimpleRouter
*
* @param array $settings
* @param \Closure $callback
* @throws \InvalidArgumentException
* @return RouteGroup
* @throws \Pecee\Http\Exceptions\MalformedUrlException
* @throws InvalidArgumentException
*/
public static function group(array $settings = [], \Closure $callback)
{
if (is_callable($callback) === false) {
throw new \InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
throw new InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
}
$group = new RouteGroup();
@@ -189,15 +198,16 @@ class SimpleRouter
* parameters and which are only rendered when the url matches.
*
* @param string $url
* @param array $settings
* @param \Closure $callback
* @throws \InvalidArgumentException
* @param array $settings
* @return RoutePartialGroup
* @throws \Pecee\Http\Exceptions\MalformedUrlException
* @throws InvalidArgumentException
*/
public static function partialGroup($url, \Closure $callback, array $settings = [])
{
if (is_callable($callback) === false) {
throw new \InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
throw new InvalidArgumentException('Invalid callback provided. Only functions or methods supported');
}
$settings['prefix'] = $url;
@@ -219,6 +229,7 @@ class SimpleRouter
* @param array|null $settings
* @see SimpleRouter::form
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function basic($url, $callback, array $settings = null)
{
@@ -234,6 +245,7 @@ class SimpleRouter
* @param array|null $settings
* @see SimpleRouter::form
* @return RouteUrl
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function form($url, $callback, array $settings = null)
{
@@ -248,6 +260,7 @@ class SimpleRouter
* @param string|\Closure $callback
* @param array|null $settings
* @return RouteUrl|IRoute
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function match(array $requestMethods, $url, $callback, array $settings = null)
{
@@ -271,6 +284,7 @@ class SimpleRouter
* @param string|\Closure $callback
* @param array|null $settings
* @return RouteUrl|IRoute
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function all($url, $callback, array $settings = null)
{
@@ -293,6 +307,7 @@ class SimpleRouter
* @param string $controller
* @param array|null $settings
* @return RouteController|IRoute
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function controller($url, $controller, array $settings = null)
{
@@ -315,6 +330,7 @@ class SimpleRouter
* @param string $controller
* @param array|null $settings
* @return RouteResource|IRoute
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function resource($url, $controller, array $settings = null)
{
@@ -335,6 +351,7 @@ class SimpleRouter
*
* @param \Closure $callback
* @return CallbackExceptionHandler $callbackHandler
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function error(\Closure $callback)
{
@@ -367,8 +384,9 @@ class SimpleRouter
* @param string|null $name
* @param string|array|null $parameters
* @param array|null $getParams
* @throws \InvalidArgumentException
* @throws \Pecee\Exceptions\InvalidArgumentException
* @return string
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function getUrl($name = null, $parameters = null, $getParams = null)
{
@@ -379,6 +397,7 @@ class SimpleRouter
* Get the request
*
* @return \Pecee\Http\Request
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function request()
{
@@ -389,6 +408,7 @@ class SimpleRouter
* Get the response object
*
* @return Response
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function response()
{
@@ -403,6 +423,7 @@ class SimpleRouter
* Returns the router instance
*
* @return Router
* @throws \Pecee\Http\Exceptions\MalformedUrlException
*/
public static function router()
{
+1 -1
View File
@@ -7,7 +7,7 @@ class ExceptionHandlerFirst implements \Pecee\Handlers\IExceptionHandler
global $stack;
$stack[] = static::class;
$request->setUri(new \Pecee\Http\Uri('/'));
$request->setUrl('/');
return $request;
}
@@ -7,7 +7,7 @@ class ExceptionHandlerSecond implements \Pecee\Handlers\IExceptionHandler
global $stack;
$stack[] = static::class;
$request->setUri(new \Pecee\Http\Uri('/'));
$request->setUrl('/');
return $request;
}
@@ -0,0 +1,16 @@
<?php
use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request;
class RewriteMiddleware implements IMiddleware {
public function handle(Request $request) {
$request->setRewriteCallback(function() {
return 'ok';
});
}
}
+6 -6
View File
@@ -3,18 +3,18 @@
class TestRouter extends \Pecee\SimpleRouter\SimpleRouter
{
public static function debugNoReset($testUri, $testMethod = 'get')
public static function debugNoReset($testUrl, $testMethod = 'get')
{
static::request()->setUri(new \Pecee\Http\Uri($testUri));
static::request()->setUrl($testUrl);
static::request()->setMethod($testMethod);
static::start();
}
public static function debug($testUri, $testMethod = 'get')
public static function debug($testUrl, $testMethod = 'get')
{
try {
static::debugNoReset($testUri, $testMethod);
static::debugNoReset($testUrl, $testMethod);
} catch(\Exception $e) {
static::router()->reset();
throw $e;
@@ -24,13 +24,13 @@ class TestRouter extends \Pecee\SimpleRouter\SimpleRouter
}
public static function debugOutput($testUri, $testMethod = 'get')
public static function debugOutput($testUrl, $testMethod = 'get')
{
$response = null;
// Route request
ob_start();
static::debug($testUri, $testMethod);
static::debug($testUrl, $testMethod);
$response = ob_get_contents();
ob_end_clean();
+104 -5
View File
@@ -5,6 +5,7 @@ require_once 'Dummy/Handler/ExceptionHandlerFirst.php';
require_once 'Dummy/Handler/ExceptionHandlerSecond.php';
require_once 'Dummy/Handler/ExceptionHandlerThird.php';
require_once 'Helpers/TestRouter.php';
require_once 'Dummy/Middlewares/RewriteMiddleware.php';
class RouteRewriteTest extends PHPUnit_Framework_TestCase
{
@@ -33,9 +34,9 @@ class RouteRewriteTest extends PHPUnit_Framework_TestCase
global $stack;
$stack = [];
TestRouter::group(['exceptionHandler' => [ExceptionHandlerFirst::class, ExceptionHandlerSecond::class]], function () {
TestRouter::group(['exceptionHandler' => [ExceptionHandlerFirst::class, ExceptionHandlerSecond::class]], function () use ($stack) {
TestRouter::group(['exceptionHandler' => ExceptionHandlerThird::class], function () {
TestRouter::group(['exceptionHandler' => ExceptionHandlerThird::class], function () use ($stack) {
TestRouter::get('/my-path', 'DummyController@method1');
@@ -64,10 +65,8 @@ class RouteRewriteTest extends PHPUnit_Framework_TestCase
TestRouter::error(function (\Pecee\Http\Request $request, \Exception $error) {
if (strtolower($request->getUri()->getPath()) == '/my/test') {
if (strtolower($request->getUrl()->getPath()) === '/my/test/') {
$request->setRewriteUrl('/another-non-existing');
return $request;
}
});
@@ -75,4 +74,104 @@ class RouteRewriteTest extends PHPUnit_Framework_TestCase
TestRouter::debug('/my/test', 'get');
}
public function testRewriteUrlFromRoute()
{
TestRouter::get('/old', function () {
TestRouter::request()->setRewriteUrl('/new');
});
TestRouter::get('/new', function () {
echo 'ok';
});
TestRouter::get('/new1', function () {
echo 'ok';
});
TestRouter::get('/new2', function () {
echo 'ok';
});
$output = TestRouter::debugOutput('/old');
$this->assertEquals('ok', $output);
}
public function testRewriteCallbackFromRoute()
{
TestRouter::get('/old', function () {
TestRouter::request()->setRewriteUrl('/new');
});
TestRouter::get('/new', function () {
return 'ok';
});
TestRouter::get('/new1', function () {
return 'fail';
});
TestRouter::get('/new/2', function () {
return 'fail';
});
$output = TestRouter::debugOutput('/old');
TestRouter::router()->reset();
$this->assertEquals('ok', $output);
}
public function testRewriteRouteFromRoute()
{
TestRouter::get('/match', function () {
TestRouter::request()->setRewriteRoute(new \Pecee\SimpleRouter\Route\RouteUrl('/match', function () {
return 'ok';
}));
});
TestRouter::get('/old1', function () {
return 'fail';
});
TestRouter::get('/old/2', function () {
return 'fail';
});
TestRouter::get('/new2', function () {
return 'fail';
});
$output = TestRouter::debugOutput('/match');
TestRouter::router()->reset();
$this->assertEquals('ok', $output);
}
public function testMiddlewareRewrite()
{
TestRouter::group(['middleware' => 'RewriteMiddleware'], function () {
TestRouter::get('/', function () {
return 'fail';
});
TestRouter::get('no/match', function () {
return 'fail';
});
});
$output = TestRouter::debugOutput('/');
$this->assertEquals('ok', $output);
}
}