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
|
/.phpunit.result.cache
|
||||||
.idea
|
.idea
|
||||||
/*.db
|
/*.db
|
||||||
|
.env
|
@ -19,6 +19,7 @@
|
|||||||
"symfony/dom-crawler": "^6.2",
|
"symfony/dom-crawler": "^6.2",
|
||||||
"symfony/css-selector": "^6.2",
|
"symfony/css-selector": "^6.2",
|
||||||
"symfony/http-client": "^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",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "352975aee49cdf2b7ee0c1f9a6ced635",
|
"content-hash": "f62bc46a34451432be93743680515868",
|
||||||
"packages": [
|
"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",
|
"name": "league/uri",
|
||||||
"version": "6.8.0",
|
"version": "6.8.0",
|
||||||
@ -246,6 +308,81 @@
|
|||||||
},
|
},
|
||||||
"time": "2022-08-18T16:18:26+00:00"
|
"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",
|
"name": "psr/container",
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
@ -935,6 +1072,89 @@
|
|||||||
],
|
],
|
||||||
"time": "2022-11-03T14:55:06+00:00"
|
"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",
|
"name": "symfony/service-contracts",
|
||||||
"version": "v3.2.1",
|
"version": "v3.2.1",
|
||||||
@ -1019,6 +1239,90 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-03-01T10:32:47+00:00"
|
"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": [
|
"packages-dev": [
|
||||||
|
10
index.php
10
index.php
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
require_once __DIR__ . "/vendor/autoload.php";
|
require_once __DIR__ . "/vendor/autoload.php";
|
||||||
|
|
||||||
|
use Lewisdale\Webmentions\Api\WebmentionApi;
|
||||||
use Lewisdale\Webmentions\Endpoint;
|
use Lewisdale\Webmentions\Endpoint;
|
||||||
use Lewisdale\Webmentions\Exceptions\InvalidSourceException;
|
use Lewisdale\Webmentions\Exceptions\InvalidSourceException;
|
||||||
use Lewisdale\Webmentions\Exceptions\InvalidTargetException;
|
use Lewisdale\Webmentions\Exceptions\InvalidTargetException;
|
||||||
@ -16,10 +17,13 @@ use Lewisdale\Webmentions\Router\StatusCode;
|
|||||||
use Lewisdale\Webmentions\Webmention;
|
use Lewisdale\Webmentions\Webmention;
|
||||||
use Symfony\Component\HttpClient\HttpClient;
|
use Symfony\Component\HttpClient\HttpClient;
|
||||||
|
|
||||||
$router = new Router();
|
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
|
||||||
$gateway = new SqliteGateway("webmentions.db");
|
$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) {
|
$router->post("/send", function (Request $req, Response $response) {
|
||||||
$mentioner = new Webmention();
|
$mentioner = new Webmention();
|
||||||
|
@ -19,6 +19,11 @@ class WebmentionApi
|
|||||||
// List Webmentions. Optionally filter by target.
|
// List Webmentions. Optionally filter by target.
|
||||||
public function list(Request $request, Response $response)
|
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;
|
$target = array_key_exists("post", $request->query) ? $request->query["post"] : null;
|
||||||
$mentions = !empty($target) ? $this->gateway->getByPost($target) : $this->gateway->list();
|
$mentions = !empty($target) ? $this->gateway->getByPost($target) : $this->gateway->list();
|
||||||
return $response->json($mentions);
|
return $response->json($mentions);
|
||||||
@ -27,6 +32,11 @@ class WebmentionApi
|
|||||||
// Get a webmention by ID
|
// Get a webmention by ID
|
||||||
public function get(Request $request, Response $response)
|
public function get(Request $request, Response $response)
|
||||||
{
|
{
|
||||||
|
if (!$this->verifyUser($request)) {
|
||||||
|
$response->status_code = StatusCode::Unauthorized;
|
||||||
|
return "Unauthorized";
|
||||||
|
}
|
||||||
|
|
||||||
$id = (int)$request->params[0];
|
$id = (int)$request->params[0];
|
||||||
|
|
||||||
if ($id) {
|
if ($id) {
|
||||||
@ -40,4 +50,25 @@ class WebmentionApi
|
|||||||
|
|
||||||
$response->status_code = StatusCode::NotFound;
|
$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;
|
namespace Lewisdale\Webmentions\Router;
|
||||||
|
|
||||||
class Request {
|
class Request
|
||||||
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public array $params,
|
public array $params,
|
||||||
public readonly string $uri,
|
public readonly string $uri,
|
||||||
public readonly Method $method,
|
public readonly Method $method,
|
||||||
public readonly array $post = [],
|
public readonly array $post = [],
|
||||||
public readonly array $query = [],
|
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.
|
* 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.
|
* It's not great, and currently on supports two methods: GET and POST.
|
||||||
*
|
*
|
||||||
* Usage is as follows:
|
* Usage is as follows:
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* $router = new Lewisdale\Webmentions\Router\Router();
|
* $router = new Lewisdale\Webmentions\Router\Router();
|
||||||
* $router->get('/a/get/route', function($request, $response) {
|
* $router->get('/a/get/route', function($request, $response) {
|
||||||
* $response->status_code = StatusCode::OK;
|
* $response->status_code = StatusCode::OK;
|
||||||
* return "Hello world!";
|
* return "Hello world!";
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* $router->get('/a/json/route', function($request, $response) {
|
* $router->get('/a/json/route', function($request, $response) {
|
||||||
* return $response->json(new MyClass());
|
* return $response->json(new MyClass());
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* $router->dispatch();
|
* $router->dispatch();
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* TL;DR? Don't use this. There are some good routing libraries already.
|
* TL;DR? Don't use this. There are some good routing libraries already.
|
||||||
*
|
*
|
||||||
* But if you're reading this, it's already too late.
|
* But if you're reading this, it's already too late.
|
||||||
*/
|
*/
|
||||||
class Router {
|
class Router
|
||||||
|
{
|
||||||
private array $routes;
|
private array $routes;
|
||||||
|
|
||||||
private function trim_route(string $route): string {
|
private function trim_route(string $route): string
|
||||||
|
{
|
||||||
$route = $route == "/" ? $route : rtrim($route, "/");
|
$route = $route == "/" ? $route : rtrim($route, "/");
|
||||||
$route = str_replace("/", "\/", $route);
|
$route = str_replace("/", "\/", $route);
|
||||||
|
|
||||||
return $route;
|
return $route;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function format_route(string $route): string {
|
private function format_route(string $route): string
|
||||||
|
{
|
||||||
$formatted = $this->trim_route($route);
|
$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);
|
$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);
|
$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(
|
return array_map(
|
||||||
function($match) { return $match[0]; },
|
function ($match) {
|
||||||
|
return $match[0];
|
||||||
|
},
|
||||||
array_shift($matches)
|
array_shift($matches)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function dispatch() {
|
public function dispatch()
|
||||||
|
{
|
||||||
$uri = $_SERVER['REQUEST_URI'];
|
$uri = $_SERVER['REQUEST_URI'];
|
||||||
$method = Method::from($_SERVER['REQUEST_METHOD']);
|
$method = Method::from($_SERVER['REQUEST_METHOD']);
|
||||||
|
|
||||||
@ -67,9 +76,9 @@ class Router {
|
|||||||
|
|
||||||
$response = new Response();
|
$response = new Response();
|
||||||
|
|
||||||
foreach($this->routes as $route) {
|
foreach ($this->routes as $route) {
|
||||||
if ($method == $route->type) {
|
if ($method == $route->type) {
|
||||||
$matches = array();
|
$matches = [];
|
||||||
if (preg_match_all($route->pattern, $uri, $matches)) {
|
if (preg_match_all($route->pattern, $uri, $matches)) {
|
||||||
$num_matched++;
|
$num_matched++;
|
||||||
$fn = $route->fn;
|
$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());
|
http_response_code($response->status_code->code());
|
||||||
|
|
||||||
echo $response->body;
|
echo $response->body;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function construct_request_object(array $params)
|
private function construct_request_object(array $params)
|
||||||
{
|
{
|
||||||
$uri = $_SERVER['REQUEST_URI'];
|
$uri = $_SERVER['REQUEST_URI'];
|
||||||
@ -107,7 +117,7 @@ class Router {
|
|||||||
$query = $_GET;
|
$query = $_GET;
|
||||||
$post = $_POST;
|
$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;
|
namespace Lewisdale\Webmentions\Router;
|
||||||
|
|
||||||
enum StatusCode {
|
enum StatusCode
|
||||||
|
{
|
||||||
case NotFound;
|
case NotFound;
|
||||||
case Ok;
|
case Ok;
|
||||||
case Redirect;
|
case Redirect;
|
||||||
case InternalError;
|
case InternalError;
|
||||||
case BadRequest;
|
case BadRequest;
|
||||||
case Created;
|
case Created;
|
||||||
|
case Forbidden;
|
||||||
|
case Unauthorized;
|
||||||
|
|
||||||
public function code() : int
|
public function code(): int
|
||||||
{
|
{
|
||||||
return match($this) {
|
return match ($this) {
|
||||||
StatusCode::NotFound => 404,
|
StatusCode::NotFound => 404,
|
||||||
StatusCode::Ok => 200,
|
StatusCode::Ok => 200,
|
||||||
StatusCode::InternalError => 500,
|
StatusCode::InternalError => 500,
|
||||||
StatusCode::Redirect => 301,
|
StatusCode::Redirect => 301,
|
||||||
StatusCode::BadRequest => 400,
|
StatusCode::BadRequest => 400,
|
||||||
|
StatusCode::Unauthorized => 401,
|
||||||
|
StatusCode::Forbidden => 403,
|
||||||
StatusCode::Created => 201,
|
StatusCode::Created => 201,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user