Add some rudimentary authentication to the API
This commit is contained in:
		
							parent
							
								
									7dc9d0a5cb
								
							
						
					
					
						commit
						4c4fffaf9d
					
				
							
								
								
									
										3
									
								
								.env.sample
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.env.sample
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
USERNAME="a-username"
 | 
			
		||||
PASSWORD="a-password"
 | 
			
		||||
DB="db-name"
 | 
			
		||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -2,3 +2,4 @@
 | 
			
		||||
/.phpunit.result.cache
 | 
			
		||||
.idea
 | 
			
		||||
/*.db
 | 
			
		||||
.env
 | 
			
		||||
@ -19,6 +19,7 @@
 | 
			
		||||
        "symfony/dom-crawler": "^6.2",
 | 
			
		||||
        "symfony/css-selector": "^6.2",
 | 
			
		||||
        "symfony/http-client": "^6.2",
 | 
			
		||||
        "league/uri": "^6.8"
 | 
			
		||||
        "league/uri": "^6.8",
 | 
			
		||||
        "vlucas/phpdotenv": "^5.5"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										306
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										306
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							@ -4,8 +4,70 @@
 | 
			
		||||
        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
 | 
			
		||||
        "This file is @generated automatically"
 | 
			
		||||
    ],
 | 
			
		||||
    "content-hash": "352975aee49cdf2b7ee0c1f9a6ced635",
 | 
			
		||||
    "content-hash": "f62bc46a34451432be93743680515868",
 | 
			
		||||
    "packages": [
 | 
			
		||||
        {
 | 
			
		||||
            "name": "graham-campbell/result-type",
 | 
			
		||||
            "version": "v1.1.1",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/GrahamCampbell/Result-Type.git",
 | 
			
		||||
                "reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831",
 | 
			
		||||
                "reference": "672eff8cf1d6fe1ef09ca0f89c4b287d6a3eb831",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "php": "^7.2.5 || ^8.0",
 | 
			
		||||
                "phpoption/phpoption": "^1.9.1"
 | 
			
		||||
            },
 | 
			
		||||
            "require-dev": {
 | 
			
		||||
                "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12"
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "GrahamCampbell\\ResultType\\": "src/"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "MIT"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Graham Campbell",
 | 
			
		||||
                    "email": "hello@gjcampbell.co.uk",
 | 
			
		||||
                    "homepage": "https://github.com/GrahamCampbell"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "An Implementation Of The Result Type",
 | 
			
		||||
            "keywords": [
 | 
			
		||||
                "Graham Campbell",
 | 
			
		||||
                "GrahamCampbell",
 | 
			
		||||
                "Result Type",
 | 
			
		||||
                "Result-Type",
 | 
			
		||||
                "result"
 | 
			
		||||
            ],
 | 
			
		||||
            "support": {
 | 
			
		||||
                "issues": "https://github.com/GrahamCampbell/Result-Type/issues",
 | 
			
		||||
                "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.1"
 | 
			
		||||
            },
 | 
			
		||||
            "funding": [
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://github.com/GrahamCampbell",
 | 
			
		||||
                    "type": "github"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type",
 | 
			
		||||
                    "type": "tidelift"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2023-02-25T20:23:15+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "league/uri",
 | 
			
		||||
            "version": "6.8.0",
 | 
			
		||||
@ -246,6 +308,81 @@
 | 
			
		||||
            },
 | 
			
		||||
            "time": "2022-08-18T16:18:26+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "phpoption/phpoption",
 | 
			
		||||
            "version": "1.9.1",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/schmittjoh/php-option.git",
 | 
			
		||||
                "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dd3a383e599f49777d8b628dadbb90cae435b87e",
 | 
			
		||||
                "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "php": "^7.2.5 || ^8.0"
 | 
			
		||||
            },
 | 
			
		||||
            "require-dev": {
 | 
			
		||||
                "bamarni/composer-bin-plugin": "^1.8.2",
 | 
			
		||||
                "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12"
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "extra": {
 | 
			
		||||
                "bamarni-bin": {
 | 
			
		||||
                    "bin-links": true,
 | 
			
		||||
                    "forward-command": true
 | 
			
		||||
                },
 | 
			
		||||
                "branch-alias": {
 | 
			
		||||
                    "dev-master": "1.9-dev"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "PhpOption\\": "src/PhpOption/"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "Apache-2.0"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Johannes M. Schmitt",
 | 
			
		||||
                    "email": "schmittjoh@gmail.com",
 | 
			
		||||
                    "homepage": "https://github.com/schmittjoh"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Graham Campbell",
 | 
			
		||||
                    "email": "hello@gjcampbell.co.uk",
 | 
			
		||||
                    "homepage": "https://github.com/GrahamCampbell"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "Option Type for PHP",
 | 
			
		||||
            "keywords": [
 | 
			
		||||
                "language",
 | 
			
		||||
                "option",
 | 
			
		||||
                "php",
 | 
			
		||||
                "type"
 | 
			
		||||
            ],
 | 
			
		||||
            "support": {
 | 
			
		||||
                "issues": "https://github.com/schmittjoh/php-option/issues",
 | 
			
		||||
                "source": "https://github.com/schmittjoh/php-option/tree/1.9.1"
 | 
			
		||||
            },
 | 
			
		||||
            "funding": [
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://github.com/GrahamCampbell",
 | 
			
		||||
                    "type": "github"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption",
 | 
			
		||||
                    "type": "tidelift"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2023-02-25T19:38:58+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "psr/container",
 | 
			
		||||
            "version": "2.0.2",
 | 
			
		||||
@ -935,6 +1072,89 @@
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2022-11-03T14:55:06+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "symfony/polyfill-php80",
 | 
			
		||||
            "version": "v1.27.0",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/symfony/polyfill-php80.git",
 | 
			
		||||
                "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
 | 
			
		||||
                "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "php": ">=7.1"
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "extra": {
 | 
			
		||||
                "branch-alias": {
 | 
			
		||||
                    "dev-main": "1.27-dev"
 | 
			
		||||
                },
 | 
			
		||||
                "thanks": {
 | 
			
		||||
                    "name": "symfony/polyfill",
 | 
			
		||||
                    "url": "https://github.com/symfony/polyfill"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "files": [
 | 
			
		||||
                    "bootstrap.php"
 | 
			
		||||
                ],
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "Symfony\\Polyfill\\Php80\\": ""
 | 
			
		||||
                },
 | 
			
		||||
                "classmap": [
 | 
			
		||||
                    "Resources/stubs"
 | 
			
		||||
                ]
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "MIT"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Ion Bazan",
 | 
			
		||||
                    "email": "ion.bazan@gmail.com"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Nicolas Grekas",
 | 
			
		||||
                    "email": "p@tchwork.com"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Symfony Community",
 | 
			
		||||
                    "homepage": "https://symfony.com/contributors"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
 | 
			
		||||
            "homepage": "https://symfony.com",
 | 
			
		||||
            "keywords": [
 | 
			
		||||
                "compatibility",
 | 
			
		||||
                "polyfill",
 | 
			
		||||
                "portable",
 | 
			
		||||
                "shim"
 | 
			
		||||
            ],
 | 
			
		||||
            "support": {
 | 
			
		||||
                "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
 | 
			
		||||
            },
 | 
			
		||||
            "funding": [
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://symfony.com/sponsor",
 | 
			
		||||
                    "type": "custom"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://github.com/fabpot",
 | 
			
		||||
                    "type": "github"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
 | 
			
		||||
                    "type": "tidelift"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2022-11-03T14:55:06+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "symfony/service-contracts",
 | 
			
		||||
            "version": "v3.2.1",
 | 
			
		||||
@ -1019,6 +1239,90 @@
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2023-03-01T10:32:47+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "vlucas/phpdotenv",
 | 
			
		||||
            "version": "v5.5.0",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/vlucas/phpdotenv.git",
 | 
			
		||||
                "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7",
 | 
			
		||||
                "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "ext-pcre": "*",
 | 
			
		||||
                "graham-campbell/result-type": "^1.0.2",
 | 
			
		||||
                "php": "^7.1.3 || ^8.0",
 | 
			
		||||
                "phpoption/phpoption": "^1.8",
 | 
			
		||||
                "symfony/polyfill-ctype": "^1.23",
 | 
			
		||||
                "symfony/polyfill-mbstring": "^1.23.1",
 | 
			
		||||
                "symfony/polyfill-php80": "^1.23.1"
 | 
			
		||||
            },
 | 
			
		||||
            "require-dev": {
 | 
			
		||||
                "bamarni/composer-bin-plugin": "^1.4.1",
 | 
			
		||||
                "ext-filter": "*",
 | 
			
		||||
                "phpunit/phpunit": "^7.5.20 || ^8.5.30 || ^9.5.25"
 | 
			
		||||
            },
 | 
			
		||||
            "suggest": {
 | 
			
		||||
                "ext-filter": "Required to use the boolean validator."
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "extra": {
 | 
			
		||||
                "bamarni-bin": {
 | 
			
		||||
                    "bin-links": true,
 | 
			
		||||
                    "forward-command": true
 | 
			
		||||
                },
 | 
			
		||||
                "branch-alias": {
 | 
			
		||||
                    "dev-master": "5.5-dev"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "Dotenv\\": "src/"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "BSD-3-Clause"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Graham Campbell",
 | 
			
		||||
                    "email": "hello@gjcampbell.co.uk",
 | 
			
		||||
                    "homepage": "https://github.com/GrahamCampbell"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Vance Lucas",
 | 
			
		||||
                    "email": "vance@vancelucas.com",
 | 
			
		||||
                    "homepage": "https://github.com/vlucas"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.",
 | 
			
		||||
            "keywords": [
 | 
			
		||||
                "dotenv",
 | 
			
		||||
                "env",
 | 
			
		||||
                "environment"
 | 
			
		||||
            ],
 | 
			
		||||
            "support": {
 | 
			
		||||
                "issues": "https://github.com/vlucas/phpdotenv/issues",
 | 
			
		||||
                "source": "https://github.com/vlucas/phpdotenv/tree/v5.5.0"
 | 
			
		||||
            },
 | 
			
		||||
            "funding": [
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://github.com/GrahamCampbell",
 | 
			
		||||
                    "type": "github"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv",
 | 
			
		||||
                    "type": "tidelift"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2022-10-16T01:01:54+00:00"
 | 
			
		||||
        }
 | 
			
		||||
    ],
 | 
			
		||||
    "packages-dev": [
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								index.php
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								index.php
									
									
									
									
									
								
							@ -2,6 +2,7 @@
 | 
			
		||||
 | 
			
		||||
require_once __DIR__ . "/vendor/autoload.php";
 | 
			
		||||
 | 
			
		||||
use Lewisdale\Webmentions\Api\WebmentionApi;
 | 
			
		||||
use Lewisdale\Webmentions\Endpoint;
 | 
			
		||||
use Lewisdale\Webmentions\Exceptions\InvalidSourceException;
 | 
			
		||||
use Lewisdale\Webmentions\Exceptions\InvalidTargetException;
 | 
			
		||||
@ -16,10 +17,13 @@ use Lewisdale\Webmentions\Router\StatusCode;
 | 
			
		||||
use Lewisdale\Webmentions\Webmention;
 | 
			
		||||
use Symfony\Component\HttpClient\HttpClient;
 | 
			
		||||
 | 
			
		||||
$router = new Router();
 | 
			
		||||
$gateway = new SqliteGateway("webmentions.db");
 | 
			
		||||
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
 | 
			
		||||
$dotenv->load();
 | 
			
		||||
 | 
			
		||||
$apiController = new \Lewisdale\Webmentions\Api\WebmentionApi($gateway);
 | 
			
		||||
$router = new Router();
 | 
			
		||||
$gateway = new SqliteGateway($_ENV["DB"]);
 | 
			
		||||
 | 
			
		||||
$apiController = new WebmentionApi($gateway);
 | 
			
		||||
 | 
			
		||||
$router->post("/send", function (Request $req, Response $response) {
 | 
			
		||||
    $mentioner = new Webmention();
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,11 @@ class WebmentionApi
 | 
			
		||||
    // List Webmentions. Optionally filter by target.
 | 
			
		||||
    public function list(Request $request, Response $response)
 | 
			
		||||
    {
 | 
			
		||||
        if (!$this->verifyUser($request)) {
 | 
			
		||||
            $response->status_code = StatusCode::Unauthorized;
 | 
			
		||||
            return "Unauthorized";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $target = array_key_exists("post", $request->query) ? $request->query["post"] : null;
 | 
			
		||||
        $mentions = !empty($target) ? $this->gateway->getByPost($target) : $this->gateway->list();
 | 
			
		||||
        return $response->json($mentions);
 | 
			
		||||
@ -27,6 +32,11 @@ class WebmentionApi
 | 
			
		||||
    // Get a webmention by ID
 | 
			
		||||
    public function get(Request $request, Response $response)
 | 
			
		||||
    {
 | 
			
		||||
        if (!$this->verifyUser($request)) {
 | 
			
		||||
            $response->status_code = StatusCode::Unauthorized;
 | 
			
		||||
            return "Unauthorized";
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        $id = (int)$request->params[0];
 | 
			
		||||
 | 
			
		||||
        if ($id) {
 | 
			
		||||
@ -40,4 +50,25 @@ class WebmentionApi
 | 
			
		||||
 | 
			
		||||
        $response->status_code = StatusCode::NotFound;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function verifyUser(Request $request): bool
 | 
			
		||||
    {
 | 
			
		||||
        if (!array_key_exists("authorization", $request->headers)) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [, $auth] = explode("Basic ", $request->headers["authorization"]);
 | 
			
		||||
 | 
			
		||||
        if (empty($auth)) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [$username, $password] = explode(":", base64_decode($auth));
 | 
			
		||||
 | 
			
		||||
        if (!empty($username) && $username === $_ENV["USERNAME"] && !empty($password) && $password === $_ENV["PASSWORD"]) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -2,14 +2,18 @@
 | 
			
		||||
 | 
			
		||||
namespace Lewisdale\Webmentions\Router;
 | 
			
		||||
 | 
			
		||||
class Request {
 | 
			
		||||
class Request
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        public array $params,
 | 
			
		||||
        public array           $params,
 | 
			
		||||
        public readonly string $uri,
 | 
			
		||||
        public readonly Method $method,
 | 
			
		||||
        public readonly array $post = [],
 | 
			
		||||
        public readonly array $query = [],
 | 
			
		||||
    ) {}
 | 
			
		||||
        public readonly array  $post = [],
 | 
			
		||||
        public readonly array  $query = [],
 | 
			
		||||
        public readonly array  $headers = [],
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
?>
 | 
			
		||||
@ -6,60 +6,69 @@ use Exception;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This is a dumb, custom Router I slapped together as a way of reminding myself how to PHP.
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * It's not great, and currently on supports two methods: GET and POST.
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * Usage is as follows:
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * ```
 | 
			
		||||
 * $router = new Lewisdale\Webmentions\Router\Router();
 | 
			
		||||
 * $router->get('/a/get/route', function($request, $response) {
 | 
			
		||||
 *  $response->status_code = StatusCode::OK;
 | 
			
		||||
 *  return "Hello world!";
 | 
			
		||||
 * });
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * $router->get('/a/json/route', function($request, $response) {
 | 
			
		||||
 *  return $response->json(new MyClass());
 | 
			
		||||
 * });
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * $router->dispatch();
 | 
			
		||||
 * ```
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * TL;DR? Don't use this. There are some good routing libraries already.
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * But if you're reading this, it's already too late.
 | 
			
		||||
 */
 | 
			
		||||
class Router {
 | 
			
		||||
class Router
 | 
			
		||||
{
 | 
			
		||||
    private array $routes;
 | 
			
		||||
 | 
			
		||||
    private function trim_route(string $route): string {
 | 
			
		||||
    private function trim_route(string $route): string
 | 
			
		||||
    {
 | 
			
		||||
        $route = $route == "/" ? $route : rtrim($route, "/");
 | 
			
		||||
        $route = str_replace("/", "\/", $route);
 | 
			
		||||
 | 
			
		||||
        return $route;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function format_route(string $route): string {
 | 
			
		||||
    private function format_route(string $route): string
 | 
			
		||||
    {
 | 
			
		||||
        $formatted = $this->trim_route($route);
 | 
			
		||||
        return "#^$formatted$#";      
 | 
			
		||||
        return "#^$formatted$#";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function get(string $route, callable $fn) {
 | 
			
		||||
    public function get(string $route, callable $fn)
 | 
			
		||||
    {
 | 
			
		||||
        $this->routes[] = new Route(Method::GET, $this->format_route($route), $fn);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function post(string $route, callable $fn) {
 | 
			
		||||
    public function post(string $route, callable $fn)
 | 
			
		||||
    {
 | 
			
		||||
        $this->routes[] = new Route(Method::POST, $this->format_route($route), $fn);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function get_params(array $matches): array {
 | 
			
		||||
    private function get_params(array $matches): array
 | 
			
		||||
    {
 | 
			
		||||
        return array_map(
 | 
			
		||||
            function($match) { return $match[0]; },
 | 
			
		||||
            function ($match) {
 | 
			
		||||
                return $match[0];
 | 
			
		||||
            },
 | 
			
		||||
            array_shift($matches)
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function dispatch() {
 | 
			
		||||
    public function dispatch()
 | 
			
		||||
    {
 | 
			
		||||
        $uri = $_SERVER['REQUEST_URI'];
 | 
			
		||||
        $method = Method::from($_SERVER['REQUEST_METHOD']);
 | 
			
		||||
 | 
			
		||||
@ -67,9 +76,9 @@ class Router {
 | 
			
		||||
 | 
			
		||||
        $response = new Response();
 | 
			
		||||
 | 
			
		||||
        foreach($this->routes as $route) {
 | 
			
		||||
        foreach ($this->routes as $route) {
 | 
			
		||||
            if ($method == $route->type) {
 | 
			
		||||
                $matches = array();
 | 
			
		||||
                $matches = [];
 | 
			
		||||
                if (preg_match_all($route->pattern, $uri, $matches)) {
 | 
			
		||||
                    $num_matched++;
 | 
			
		||||
                    $fn = $route->fn;
 | 
			
		||||
@ -94,12 +103,13 @@ class Router {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private function respond(Response $response) {
 | 
			
		||||
    private function respond(Response $response)
 | 
			
		||||
    {
 | 
			
		||||
        http_response_code($response->status_code->code());
 | 
			
		||||
 | 
			
		||||
        echo $response->body;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    private function construct_request_object(array $params)
 | 
			
		||||
    {
 | 
			
		||||
        $uri = $_SERVER['REQUEST_URI'];
 | 
			
		||||
@ -107,7 +117,7 @@ class Router {
 | 
			
		||||
        $query = $_GET;
 | 
			
		||||
        $post = $_POST;
 | 
			
		||||
 | 
			
		||||
        return new Request($params, $uri, $method, $post, $query);
 | 
			
		||||
        return new Request($params, $uri, $method, $post, $query, array_change_key_case(getallheaders(), CASE_LOWER));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,22 +2,27 @@
 | 
			
		||||
 | 
			
		||||
namespace Lewisdale\Webmentions\Router;
 | 
			
		||||
 | 
			
		||||
enum StatusCode {
 | 
			
		||||
enum StatusCode
 | 
			
		||||
{
 | 
			
		||||
    case NotFound;
 | 
			
		||||
    case Ok;
 | 
			
		||||
    case Redirect;
 | 
			
		||||
    case InternalError;
 | 
			
		||||
    case BadRequest;
 | 
			
		||||
    case Created;
 | 
			
		||||
    case Forbidden;
 | 
			
		||||
    case Unauthorized;
 | 
			
		||||
 | 
			
		||||
    public function code() : int
 | 
			
		||||
    public function code(): int
 | 
			
		||||
    {
 | 
			
		||||
        return match($this) {
 | 
			
		||||
        return match ($this) {
 | 
			
		||||
            StatusCode::NotFound => 404,
 | 
			
		||||
            StatusCode::Ok => 200,
 | 
			
		||||
            StatusCode::InternalError => 500,
 | 
			
		||||
            StatusCode::Redirect => 301,
 | 
			
		||||
            StatusCode::BadRequest => 400,
 | 
			
		||||
            StatusCode::Unauthorized => 401,
 | 
			
		||||
            StatusCode::Forbidden => 403,
 | 
			
		||||
            StatusCode::Created => 201,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user