You've already forked Traefik-Redis-Api
203 lines
6.9 KiB
PHP
203 lines
6.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Siteworxpro\App;
|
|
|
|
use Illuminate\Container\Container;
|
|
use Illuminate\Database\Capsule\Manager;
|
|
use Illuminate\Support\Facades\Facade;
|
|
use League\Route\Http\Exception\MethodNotAllowedException;
|
|
use League\Route\Http\Exception\NotFoundException;
|
|
use League\Route\RouteGroup;
|
|
use League\Route\Router;
|
|
use League\Route\Strategy\JsonStrategy;
|
|
use Nyholm\Psr7\Factory\Psr17Factory;
|
|
use Siteworxpro\App\Controllers\MiddlewaresController;
|
|
use Siteworxpro\App\Controllers\RoutesController;
|
|
use Siteworxpro\App\Controllers\ServicesController;
|
|
use Siteworxpro\App\Facades\Config;
|
|
use Siteworxpro\App\Facades\Logger;
|
|
use Siteworxpro\App\Http\JsonResponseFactory;
|
|
use Siteworxpro\App\Http\Middleware\CorsMiddleware;
|
|
use Spiral\RoadRunner\Http\PSR7Worker;
|
|
use Spiral\RoadRunner\Worker;
|
|
|
|
/**
|
|
* Class Server
|
|
*
|
|
* This class represents the main server application.
|
|
* It handles incoming HTTP requests, routes them to the appropriate handlers,
|
|
* and manages the server lifecycle.
|
|
*
|
|
* @package Siteworxpro\App
|
|
*/
|
|
class Server
|
|
{
|
|
/**
|
|
* @var Router The router instance for handling routes.
|
|
*/
|
|
protected Router $router;
|
|
|
|
/**
|
|
* @var PSR7Worker The PSR-7 worker instance for handling HTTP requests.
|
|
*/
|
|
protected PSR7Worker $worker;
|
|
|
|
|
|
/**
|
|
* Server constructor.
|
|
*
|
|
* Initializes the server by booting the PSR-7 worker and router.
|
|
*/
|
|
public function __construct()
|
|
{
|
|
$this->boot();
|
|
}
|
|
|
|
/**
|
|
* Bootstraps the server by initializing the PSR-7 worker and router.
|
|
*
|
|
* This method sets up the PSR-7 worker and router instances, and registers
|
|
* the routes for the server. It should be called in the constructor of
|
|
* subclasses to ensure proper initialization.
|
|
*
|
|
* @return void
|
|
*/
|
|
private function boot(): void
|
|
{
|
|
$container = new Container();
|
|
Facade::setFacadeApplication($container);
|
|
|
|
$this->worker = new PSR7Worker(
|
|
Worker::create(),
|
|
new Psr17Factory(),
|
|
new Psr17Factory(),
|
|
new Psr17Factory()
|
|
);
|
|
|
|
$this->router = new Router();
|
|
$this->router->setStrategy(new JsonStrategy(new JsonResponseFactory()));
|
|
|
|
$this->registerRoutes();
|
|
// $this->bootModelCapsule(); // no db
|
|
}
|
|
|
|
/**
|
|
* Bootstraps the model capsule for database connections.
|
|
*
|
|
* This method sets up the database connection using the Eloquent ORM.
|
|
* It retrieves the database configuration from the Config facade and
|
|
* initializes the Eloquent capsule manager.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function bootModelCapsule(): void
|
|
{
|
|
$capsule = new Manager();
|
|
$capsule->addConnection([
|
|
'driver' => Config::get('db.driver'),
|
|
'host' => Config::get('db.host'),
|
|
'database' => Config::get('db.database'),
|
|
'username' => Config::get('db.username'),
|
|
'password' => Config::get('db.password'),
|
|
'charset' => 'utf8',
|
|
'collation' => 'utf8_unicode_ci',
|
|
'prefix' => '',
|
|
]);
|
|
|
|
$capsule->setAsGlobal();
|
|
$capsule->bootEloquent();
|
|
}
|
|
|
|
/**
|
|
* Registers the routes for the server.
|
|
*
|
|
* This method is responsible for defining the routes that the server will handle.
|
|
* It should be implemented in subclasses to provide specific route definitions.
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function registerRoutes(): void
|
|
{
|
|
$this->router->addPatternMatcher('protocolEnums', 'http|tcp|udp');
|
|
$this->router->addPatternMatcher('protocolEnumsMiddleware', 'http|tcp');
|
|
|
|
$this->router->group('/{protocol:protocolEnums}/routes', function (RouteGroup $router) {
|
|
$router->get('/', RoutesController::class . '::get');
|
|
$router->get('/{id}', RoutesController::class . '::get');
|
|
$router->post('/{id}', RoutesController::class . '::post');
|
|
$router->delete('/{id}', RoutesController::class . '::delete');
|
|
});
|
|
|
|
$this->router->group('/{protocol:protocolEnums}/services', function (RouteGroup $router) {
|
|
$router->get('/', ServicesController::class . '::get');
|
|
$router->get('/{id}', ServicesController::class . '::get');
|
|
$router->post('/{id}', ServicesController::class . '::post');
|
|
$router->delete('/{id}', ServicesController::class . '::delete');
|
|
});
|
|
|
|
$this->router->group('/{protocol:protocolEnumsMiddleware}/middlewares', function (RouteGroup $router) {
|
|
$router->get('/', MiddlewaresController::class . '::get');
|
|
$router->get('/{id}', MiddlewaresController::class . '::get');
|
|
$router->post('/{id}', MiddlewaresController::class . '::post');
|
|
$router->delete('/{id}', MiddlewaresController::class . '::delete');
|
|
});
|
|
|
|
$this->router->middleware(new CorsMiddleware());
|
|
}
|
|
|
|
/**
|
|
* Starts the server and handles incoming requests.
|
|
*
|
|
* This method enters an infinite loop to continuously handle incoming HTTP requests.
|
|
* It decodes the request body, routes the request, and sends the response. It also handles
|
|
* exceptions and ensures proper cleanup after each request.
|
|
*
|
|
* @throws \JsonException If there is an error decoding the JSON request body.
|
|
*/
|
|
public function startServer(): void
|
|
{
|
|
Logger::info(sprintf('Server started: %s', microtime(true)));
|
|
Logger::info(sprintf('Server PID: %s', getmypid()));
|
|
Logger::info(sprintf('Server Listening on: 0.0.0.0:%s', Config::get('server.port')));
|
|
|
|
while (true) {
|
|
try {
|
|
$request = $this->worker->waitRequest();
|
|
|
|
if ($request === null) {
|
|
break;
|
|
}
|
|
|
|
$request = $request->withParsedBody(json_decode($request->getBody()->getContents(), true));
|
|
|
|
$response = $this->router->handle($request);
|
|
$this->worker->respond($response);
|
|
} catch (MethodNotAllowedException | NotFoundException) {
|
|
$this->worker->respond(
|
|
JsonResponseFactory::createJsonResponse(
|
|
['status_code' => 404, 'reason_phrase' => 'Not Found'],
|
|
404
|
|
)
|
|
);
|
|
} catch (\Throwable $e) {
|
|
Logger::error($e->getMessage());
|
|
Logger::error($e->getTraceAsString());
|
|
|
|
$json = ['status_code' => 500, 'reason_phrase' => 'Server Error'];
|
|
if (Config::get("server.dev_mode")) {
|
|
$json = [
|
|
'status_code' => 500,
|
|
'reason_phrase' => 'Server Error',
|
|
'message' => $e->getMessage(),
|
|
'trace' => $e->getTraceAsString(),
|
|
];
|
|
}
|
|
|
|
$this->worker->respond(JsonResponseFactory::createJsonResponse($json, 500));
|
|
}
|
|
}
|
|
}
|
|
}
|