From 03e9f93e00856565ffa8566dd1008a9d74e258aa Mon Sep 17 00:00:00 2001 From: Artur Welp Date: Fri, 14 Aug 2026 23:38:33 -0300 Subject: [PATCH] Fixing naming. Fixing deprecated Functionts. Adding :s for slugs as Route parameter --- README.md | 193 ++++++++++++++++++++++++++++++++++++++- src/Routes/HTTPCodes.php | 57 ++++++++++++ src/Routes/Route.php | 85 ++++------------- 3 files changed, 267 insertions(+), 68 deletions(-) create mode 100644 src/Routes/HTTPCodes.php 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 {