benycode / slim-middleware
Slim 4 middleware package
Requires
- php: ^8.0
README
A Slim 4 Framework useful middlewares.
Features
- health check endpoint;
- info endpoint;
- settings setup;
- exception handler;
- APISIX auto route register;
- Leader election middleware;
- Endpoint protection with X-Api-Token.
Table of contents
- Install
- [Health check endpoint usage](#health check endpoint usage)
- [Info endpoint usage](#info endpoint usage)
- [Settings setup usage](#settings setup usage)
- [Exception handler usage](#exception handler usage)
- [APISIX auto route register usage](#apisix auto route register usage)
- [Leader election usage](#leader election usage)
- [Endpoint protection with X-Api-Token usage](#endpoint protection with X-Api-Token usage)
Install
Via Composer
$ composer require benycode/slim-middleware
Requires Slim 4.
Health check endpoint usage
Use DI to inject the library Middleware classes:
use BenyCode\Slim\Middleware\HealthCheckEndpointMiddleware; return [ ...... HealthCheckEndpointMiddleware::class => function (ContainerInterface $container) { return new HealthCheckEndpointMiddleware( [ 'health_endpoint' => '/_health', // change if needed other endpoint ], <<inject you PSR7 logger if needed>>, ); }, ...... ];
add the Middleware to any
route at the end of the routes:
use Slim\Exception\HttpNotFoundException; use BenyCode\Slim\Middleware\HealthCheckEndpointMiddleware; $app ->get( '/{any:.*}', function (Request $request, Response $response) { throw new HttpNotFoundException($request); } ) .... ->add(HealthCheckEndpointMiddleware::class) ->setName('any') ;
welcome, your app is within new path:
- /_health or your defined
create health check.
Info endpoint usage
Use DI to inject the library Middleware classes:
use BenyCode\Slim\Middleware\InfoEndpointMiddleware; return [ ...... InfoEndpointMiddleware::class => function (ContainerInterface $container) { return new InfoEndpointMiddleware( [ 'info_endpoint' => '/_info', // change if needed other endpoint ], '<<define api version here>>', // example: v0.0.0 ); }, ...... ];
add the Middleware to any
route at the end of the routes:
use Slim\Exception\HttpNotFoundException; use BenyCode\Slim\Middleware\InfoEndpointMiddleware; $app ->get( '/{any:.*}', function (Request $request, Response $response) { throw new HttpNotFoundException($request); } ) .... ->add(InfoEndpointMiddleware::class) ->setName('any') ;
welcome, your app is within new path:
- /_info
Settings setup usage
add the Middleware to a global
list:
use BenyCode\Middleware\SettingsUpMiddleware; return function (App $app) { ... $app->add(SettingsUpMiddleware::class); ... };
get the settings:
protected function __invoke(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface { $settings = $request ->getAttribute('settings') ; }
Exception handler usage
add the Middleware to a global
list:
use BenyCode\Middleware\ExceptionMiddleware; return function (App $app) { ... $app->add(ExceptionMiddleware::class); ... };
welcome, your app is within new error handler.
APISIX auto route register usage
Idea: Auto create service and routes on the health check procedure.
You can use it with:
- Docker health check;
- k8s health check;
- and more others....
Requires curl
and docker/k8s
health check mechanism.
Balanced with LeaderElectionMiddleware
, bring more stability and activate one instance registration functionality.
Use DI to inject the library Middleware classes:
use BenyCode\Slim\Middleware\APISIXRegisterMiddleware; return [ ...... APISIXRegisterMiddleware::class => function (ContainerInterface $container) { return new APISIXRegisterMiddleware( [ 'register_endpoint' => '/_health', // change if needed other endpoint 'service_id' => '<<describe your service name>>', 'service' => [ 'upstream' => [ 'type' => 'roundrobin', 'nodes' => [ '<<describe working endpoint>>:<<describe working port>>' => 1, // example: books-microservice:80 ], ], ], 'route' => [ 'uri' => "<<describe working path>>", // example: /books/* 'service_id' => '<<describe service id>>', // example: books-microservice ], 'api_admin_secret' => '<<describe APISIX admin secret>>', 'api_endpoint' => '<<describe APISIX API endpoint url>>', // example: http://api-gateway:9180 ], <<inject you PSR7 logger if needed>>, ); }, ...... ];
add the Middleware to any
route at the end of the routes:
use Slim\Exception\HttpNotFoundException; use BenyCode\Slim\Middleware\APISIXRegisterMiddleware; $app ->get( '/{any:.*}', function (Request $request, Response $response) { throw new HttpNotFoundException($request); } ) .... ->add(APISIXRegisterMiddleware::class) ->setName('any') ;
create health check /_health
or your defined.
welcome, your app will be auto (re)registered in the APISIX on the every health check.
Leader election usage
Idea: in the microservice world can be more then one instance who can execute the relevant commands and there is a need for those commands to be executed only by one. Vote for the leader using health check mechanizm!
Balanced with the APISIXRegisterMiddleware
.
You can use it with:
- Docker health check;
- k8s health check;
- and more others....
Requires curl
, docker/k8s
health check mechanism and ETCD v3
.
Use DI to inject the library Middleware classes:
use BenyCode\Slim\Middleware\LeaderElectionMiddleware; return [ ...... LeaderElectionMiddleware::class => function (ContainerInterface $container) { return new LeaderElectionMiddleware( [ 'leader_election_endpoint' => '/_health', // change if needed other endpoint 'etcd_endpoint' => '<<etcd endpoint>>', 'alection_frequency' => 5, // alection frequence in seconds <<inject you PSR7 logger if needed>>, ], ); }, ...... ];
add the Middleware to any
route at the end of the routes:
use Slim\Exception\HttpNotFoundException; use BenyCode\Slim\Middleware\LeaderElectionMiddleware; $app ->get( '/{any:.*}', function (Request $request, Response $response) { throw new HttpNotFoundException($request); } ) .... ->add(LeaderElectionMiddleware::class) ->setName('any') ;
get the leader status:
protected function __invoke(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface { $leader = $request ->getAttribute('im_leader') ; if($leader) { // the leader code } }
Endpoint protection with X-Api-Token usage
Idea: Protect you endpoints like health check with Api token.
Use DI to inject the library Middleware classes:
use BenyCode\Slim\Middleware\OnePathXApiTokenProtectionMiddleware; return [ ...... OnePathXApiTokenProtectionMiddleware::class => function (ContainerInterface $container) { return new OnePathXApiTokenProtectionMiddleware( [ 'path' => '/_health', // change if needed other endpoint 'x-api-token' => '4bfdb81c03f42600d9018103a4df878b', // change to yours <<inject you PSR7 logger if needed>>, ], ); }, ...... ];
add the Middleware to any
route at the end of the routes:
use Slim\Exception\HttpNotFoundException; use BenyCode\Slim\Middleware\OnePathXApiTokenProtectionMiddleware; $app ->get( '/{any:.*}', function (Request $request, Response $response) { throw new HttpNotFoundException($request); } ) .... ->add(OnePathXApiTokenProtectionMiddleware::class) ->setName('any') ;