Fixing naming. Fixing deprecated Functionts. Adding :s for slugs as Route parameter
This commit is contained in:
@@ -1,3 +1,192 @@
|
||||
# Routes
|
||||
# InforRoutes
|
||||
|
||||
A simple and dependency free routing system providing:
|
||||
|
||||
- Non blocking dispatch of system `WEB` and `CLI` functionalities
|
||||
- Parameters detection on the URL segments
|
||||
- Route grouping based on namespaces
|
||||
- Error handling and 404 detection
|
||||
- Attachable and global middlewares
|
||||
|
||||
## Usage
|
||||
|
||||
### Installation
|
||||
First install the package with `composer require inforsistemas/routes`. You might need to add a custom repository on the composer.json
|
||||
|
||||
```
|
||||
"repositories": [{
|
||||
"type": "composer",
|
||||
"url": "https://satis.domain.com"
|
||||
}],
|
||||
```
|
||||
|
||||
### Server configuration
|
||||
|
||||
#### Requirements
|
||||
|
||||
The following packages need to be installed for the project to run
|
||||
|
||||
* Apache
|
||||
- apache2 phpX.X phpX.X-fpm libapache2-mod-phpX.X
|
||||
* Nginx
|
||||
- nginx phpX.X phpX.X-fpm
|
||||
|
||||
The ports `80` and `443` must be open: `ufw allow 80 && ufw allow 443`
|
||||
|
||||
#### Apache
|
||||
|
||||
For apache, the basic required configuration
|
||||
|
||||
```
|
||||
<VirtualHost *:80>
|
||||
ServerAdmin webmaster@localhost
|
||||
DocumentRoot /var/www/html/public
|
||||
ServerName example.com
|
||||
|
||||
<Directory /var/www >
|
||||
Options Indexes FollowSymLinks MultiViews
|
||||
AllowOverride All
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Directory>
|
||||
|
||||
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
For a server with HTTPs, the configuration with redirection
|
||||
|
||||
```
|
||||
<VirtualHost *:80>
|
||||
ServerName example.com
|
||||
Redirect / https://example.com
|
||||
</VirtualHost>
|
||||
|
||||
<IfModule mod_ssl.c>
|
||||
<VirtualHost *:443>
|
||||
|
||||
ServerAdmin webmaster@localhost
|
||||
DocumentRoot /var/www/html/public
|
||||
ServerName urfat.com.br
|
||||
|
||||
|
||||
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||
|
||||
SSLCertificateFile /etc/letsencrypt/live/example.com.br/fullchain.pem
|
||||
SSLCertificateKeyFile /etc/letsencrypt/live/example.com.br/privkey.pem
|
||||
Include /etc/letsencrypt/options-ssl-apache.conf
|
||||
</VirtualHost>
|
||||
</IfModule>
|
||||
```
|
||||
|
||||
#### Nginx
|
||||
|
||||
*For Nginx,this is the basic required configuration with PHP-FPM*
|
||||
|
||||
```
|
||||
server {
|
||||
listen 82 default_server;
|
||||
listen [::]:82 default_server;
|
||||
|
||||
server_name example.com;
|
||||
|
||||
root /var/www/html/public;
|
||||
index index.php index.html index.htm index.nginx-debian.html;
|
||||
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php$is_args$args;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
include snippets/fastcgi-php.conf;
|
||||
#Check fpm-version
|
||||
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
|
||||
}
|
||||
|
||||
location ~ /\.ht {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For a server with HTTPs, the configuration with redirection
|
||||
|
||||
```
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
listen 443 default_server ssl;
|
||||
|
||||
server_name example.com;
|
||||
|
||||
ssl_certificate /path/to/my/cert;
|
||||
ssl_certificate_key /path/to/my/key;
|
||||
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_ciphers "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS:!AES256";
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_dhparam /path/to/my/dhp-4096.pem #sudo openssl dhparam -out /path/to/my/dhp-4096.pem 4096
|
||||
|
||||
if ($scheme = http) {
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Hello World
|
||||
|
||||
With the dependencies and the server with the correct configuration, create a index.php with the content
|
||||
|
||||
```
|
||||
<?php
|
||||
|
||||
include_once 'vendor/autoload.php';
|
||||
use Routes\RouteCollection as RouteCollection;
|
||||
|
||||
RouteCollection::get ("/", function(){
|
||||
echo "Hello World";
|
||||
});
|
||||
|
||||
RouteCollection::getInstance()->submit();
|
||||
```
|
||||
|
||||
## Inner workings
|
||||
|
||||
The package consist in 3 main files, with `RouteCollection.php` providing the main API
|
||||
|
||||
- `Route.php` => Stores each route information
|
||||
- `RouteCollection.php` => Aggregate all routes and provide a interface to interact with the routes dataset
|
||||
- `RouteGroup.php` => Aggregate a group of routes based on their namespaces
|
||||
|
||||
The class `RouteCollection` is treated as a Singleton that return it's own global instance when loaded. The main interface would be something like: `RouteCollection::add($verb, $uri, $callback, $weight = 0)`, this method will return the instance of the `Route` object, so that the Route properties can be configured
|
||||
|
||||
*Route settings:*
|
||||
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->doBlock()`
|
||||
- After this route execute, no more routes would be executed
|
||||
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->notBlock()`
|
||||
- The execution of this route will not block the execution of the next routes
|
||||
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->doIgnore()`
|
||||
- This route will not count as a executed route, so a 404 can be detected
|
||||
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->middlewareIgnore($name = '')`
|
||||
- This route will not execute a registered global middleware
|
||||
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->middlewareAdd($name = '', $params = [])`
|
||||
- Register that this route must pass by a registered middleware
|
||||
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->middlewareAppend($name = '', $function)`
|
||||
- Append a ad-hock middleware to this specific route
|
||||
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->setWeight($weigth = 0)`
|
||||
- Define the priority of this route on the execution chain
|
||||
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->setName($name)`
|
||||
- Add a property name for the route object
|
||||
- `RouteCollection::add($verb, $uri, $callback, $weight = 0)->setTag($key = '', $value = '')`
|
||||
- Add a custom arbitrary tag on the route object
|
||||
|
||||
|
||||
|
||||
## Other resources
|
||||
https://stackoverflow.com/questions/8054165/using-put-method-in-html-form
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Routes;
|
||||
|
||||
enum HTTPCodes: string
|
||||
{
|
||||
// Informational 1xx
|
||||
case 100 = 'Continue';
|
||||
case 101 = 'Switching Protocols';
|
||||
|
||||
// Successful 2xx
|
||||
case 200 = 'OK';
|
||||
case 201 = 'Created';
|
||||
case 202 = 'Accepted';
|
||||
case 203 = 'Non-Authoritative Information';
|
||||
case 204 = 'No Content';
|
||||
case 205 = 'Reset Content';
|
||||
case 206 = 'Partial Content';
|
||||
|
||||
// Redirection 3xx
|
||||
case 300 = 'Multiple Choices';
|
||||
case 301 = 'Moved Permanently';
|
||||
case 302 = 'Found';
|
||||
case 303 = 'See Other';
|
||||
case 304 = 'Not Modified';
|
||||
case 305 = 'Use Proxy';
|
||||
case 306 = '(Unused)';
|
||||
case 307 = 'Temporary Redirect';
|
||||
|
||||
// Client Error 4xx
|
||||
case 400 = 'Bad Request';
|
||||
case 401 = 'Unauthorized';
|
||||
case 402 = 'Payment Required';
|
||||
case 403 = 'Forbidden';
|
||||
case 404 = 'Not Found';
|
||||
case 405 = 'Method Not Allowed';
|
||||
case 406 = 'Not Acceptable';
|
||||
case 407 = 'Proxy Authentication Required';
|
||||
case 408 = 'Request Timeout';
|
||||
case 409 = 'Conflict';
|
||||
case 410 = 'Gone';
|
||||
case 411 = 'Length Required';
|
||||
case 412 = 'Precondition Failed';
|
||||
case 413 = 'Request Entity Too Large';
|
||||
case 414 = 'Request-URI Too Long';
|
||||
case 415 = 'Unsupported Media Type';
|
||||
case 416 = 'Requested Range Not Satisfiable';
|
||||
case 417 = 'Expectation Failed';
|
||||
|
||||
// Server Error 5xx
|
||||
case 500 = 'Internal Server Error';
|
||||
case 501 = 'Not Implemented';
|
||||
case 502 = 'Bad Gateway';
|
||||
case 503 = 'Service Unavailable';
|
||||
case 504 = 'Gateway Timeout';
|
||||
case 505 = 'HTTP Version Not Supported';
|
||||
}
|
||||
+19
-66
@@ -15,7 +15,7 @@ class Route
|
||||
* HTTP VERB
|
||||
*/
|
||||
|
||||
public $_verb = array();
|
||||
public $_verb = Array();
|
||||
/*
|
||||
* Execution Source
|
||||
* HTTP | Cli | SOAP |
|
||||
@@ -41,32 +41,32 @@ class Route
|
||||
/*
|
||||
* URI Segments
|
||||
*/
|
||||
public $_uriSegments = array();
|
||||
public $_uriSegments = Array();
|
||||
|
||||
/*
|
||||
* Extracted params
|
||||
*/
|
||||
public $_segments = array();
|
||||
public $_segments = Array();
|
||||
|
||||
/*
|
||||
* Prepared params
|
||||
*/
|
||||
public $_params = array();
|
||||
public $_params = Array();
|
||||
|
||||
/*
|
||||
* Execute before dispatch route
|
||||
*/
|
||||
public $_before = array();
|
||||
public $_before = Array();
|
||||
|
||||
/*
|
||||
* Route callback
|
||||
*/
|
||||
public $_callback = array();
|
||||
public $_callback = Array();
|
||||
|
||||
/*
|
||||
* Execute after route dispatched
|
||||
*/
|
||||
public $_after = array();
|
||||
public $_after = Array();
|
||||
|
||||
/*
|
||||
* Prepared RegEx
|
||||
@@ -91,63 +91,12 @@ class Route
|
||||
/*
|
||||
* Middlewares to remove from the list
|
||||
*/
|
||||
public $_middlewaresToIgnore = array();
|
||||
public $_middlewaresToIgnore = Array();
|
||||
|
||||
/*
|
||||
* From Klein
|
||||
* HTTP status List
|
||||
* Arbitrary tag on a route
|
||||
*/
|
||||
|
||||
public $_tags = [];
|
||||
|
||||
|
||||
protected static $httpMessages = array(
|
||||
// Informational 1xx
|
||||
100 => 'Continue',
|
||||
101 => 'Switching Protocols',
|
||||
// Successful 2xx
|
||||
200 => 'OK',
|
||||
201 => 'Created',
|
||||
202 => 'Accepted',
|
||||
203 => 'Non-Authoritative Information',
|
||||
204 => 'No Content',
|
||||
205 => 'Reset Content',
|
||||
206 => 'Partial Content',
|
||||
// Redirection 3xx
|
||||
300 => 'Multiple Choices',
|
||||
301 => 'Moved Permanently',
|
||||
302 => 'Found',
|
||||
303 => 'See Other',
|
||||
304 => 'Not Modified',
|
||||
305 => 'Use Proxy',
|
||||
306 => '(Unused)',
|
||||
307 => 'Temporary Redirect',
|
||||
// Client Error 4xx
|
||||
400 => 'Bad Request',
|
||||
401 => 'Unauthorized',
|
||||
402 => 'Payment Required',
|
||||
403 => 'Forbidden',
|
||||
404 => 'Not Found',
|
||||
405 => 'Method Not Allowed',
|
||||
406 => 'Not Acceptable',
|
||||
407 => 'Proxy Authentication Required',
|
||||
408 => 'Request Timeout',
|
||||
409 => 'Conflict',
|
||||
410 => 'Gone',
|
||||
411 => 'Length Required',
|
||||
412 => 'Precondition Failed',
|
||||
413 => 'Request Entity Too Large',
|
||||
414 => 'Request-URI Too Long',
|
||||
415 => 'Unsupported Media Type',
|
||||
416 => 'Requested Range Not Satisfiable',
|
||||
417 => 'Expectation Failed',
|
||||
// Server Error 5xx
|
||||
500 => 'Internal Server Error',
|
||||
501 => 'Not Implemented',
|
||||
502 => 'Bad Gateway',
|
||||
503 => 'Service Unavailable',
|
||||
504 => 'Gateway Timeout',
|
||||
505 => 'HTTP Version Not Supported',
|
||||
);
|
||||
public $_tags = Array();
|
||||
|
||||
//=======================================================
|
||||
function execute()
|
||||
@@ -174,8 +123,9 @@ class Route
|
||||
|
||||
$r = new \ReflectionMethod($segments[0], $segments[1]);
|
||||
|
||||
if (sizeof($r->getParameters()) > 0 && $r->getParameters()[0]->getClass() != NULL) {
|
||||
$element = $r->getParameters()[0]->getClass()->name;
|
||||
$firstType = count($r->getParameters()) > 0 ? $r->getParameters()[0]->getType() : null;
|
||||
if ($firstType instanceof \ReflectionNamedType && !$firstType->isBuiltin()) {
|
||||
$element = $firstType->getName();
|
||||
$element = new $element;
|
||||
if (isset($this->_params['id'])) {
|
||||
$element->load($this->_params['id']);
|
||||
@@ -185,8 +135,9 @@ class Route
|
||||
$class->{$segments[1]}(...array_values($this->_params));
|
||||
} else {
|
||||
$r = new \ReflectionFunction($callback);
|
||||
if (sizeof($r->getParameters()) > 0 && $r->getParameters()[0]->getClass() != NULL) {
|
||||
$element = $r->getParameters()[0]->getClass()->name;
|
||||
$firstType = count($r->getParameters()) > 0 ? $r->getParameters()[0]->getType() : null;
|
||||
if ($firstType instanceof \ReflectionNamedType && !$firstType->isBuiltin()) {
|
||||
$element = $firstType->getName();
|
||||
$element = new $element;
|
||||
if (isset($this->_params['id'])) {
|
||||
$element->load($this->_params['id']);
|
||||
@@ -213,6 +164,8 @@ class Route
|
||||
$this->_regex .= "\/[A-z]+";
|
||||
} else if (strpos($segment, 'd:') > -1) {
|
||||
$this->_regex .= "\/[A-z0-9]+";
|
||||
} else if (strpos($segment, 's:') > -1) {
|
||||
$this->_regex .= "\/[A-z0-9\-_]+";
|
||||
} else if (strpos($segment, 'r:') > -1) {
|
||||
$this->_regex .= "\/[ -~]+";
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user