diff --git a/README.md b/README.md
index bebd41a..0d03ed3 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,192 @@
-# Routes
+# InforRoutes
-https://stackoverflow.com/questions/8054165/using-put-method-in-html-form
\ No newline at end of file
+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
+
+```
+
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html/public
+ ServerName example.com
+
+
+ Options Indexes FollowSymLinks MultiViews
+ AllowOverride All
+ Order allow,deny
+ Allow from all
+
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+```
+
+For a server with HTTPs, the configuration with redirection
+
+```
+
+ ServerName example.com
+ Redirect / https://example.com
+
+
+
+
+
+ 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
+
+
+```
+
+#### 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
+
+```
+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
diff --git a/src/Routes/HTTPCodes.php b/src/Routes/HTTPCodes.php
new file mode 100644
index 0000000..a0be927
--- /dev/null
+++ b/src/Routes/HTTPCodes.php
@@ -0,0 +1,57 @@
+ '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 {