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.
This commit is contained in:
Simon Sessingo
2018-02-26 23:21:26 +01:00
parent a0c5bbdcc0
commit a25be983b8
17 changed files with 180 additions and 75 deletions
@@ -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) {
+24 -13
View File
@@ -12,7 +12,7 @@ class Request
private $data = [];
protected $headers;
protected $host;
protected $uri;
protected $url;
protected $method;
protected $input;
@@ -29,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')));
@@ -58,11 +62,11 @@ class Request
}
/**
* @return Uri
* @return Url
*/
public function getUri()
public function getUrl()
{
return $this->uri;
return $this->url;
}
/**
@@ -188,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
@@ -198,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 = is_string($url) ? new Url($url) : $url;
}
/**
@@ -282,7 +293,7 @@ class Request
{
$this->hasRewrite = true;
return $this->setRewriteRoute(new RouteUrl($this->getUri()->getPath(), $callback));
return $this->setRewriteRoute(new RouteUrl($this->getUrl()->getPath(), $callback));
}
/**
+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);
+17 -11
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) {
@@ -208,7 +216,6 @@ class Router
* @param bool $rewrite
* @return string|mixed
* @throws HttpException
* @throws \Exception
*/
public function routeRequest($rewrite = false)
{
@@ -228,7 +235,7 @@ class Router
$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) {
@@ -274,7 +281,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 +290,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));
@@ -322,7 +329,6 @@ class Router
/**
* @param \Exception $e
* @throws HttpException
* @throws \Exception
* @return string
*/
protected function handleException(\Exception $e)
@@ -354,7 +360,7 @@ class Router
}
}
throw $e;
throw new HttpException($e->getMessage(), $e->getCode(), $e->getPrevious());
}
public function arrayToParams(array $getParams = [], $includeEmpty = true)
@@ -436,13 +442,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 === '') {
@@ -458,7 +464,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()
{