You've already forked Traefik-Redis-Api
FONDLED THE CODE
This commit is contained in:
96
README.md
96
README.md
@@ -1,28 +1,104 @@
|
||||
# Traefik Redis Provider API
|
||||
|
||||
[Traefik](https://traefik.io/traefik/) is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy. This project provides
|
||||
an api manager for the [Redis provider](https://doc.traefik.io/traefik/providers/redis/) for Traefik, allowing you to use Redis as a dynamic configuration backend.
|
||||
|
||||
## Running the Project
|
||||
### Prerequisites
|
||||
- Docker
|
||||
- Traefik
|
||||
- Redis
|
||||
|
||||
### Environment Variables
|
||||
- `REDIS_HOST`: The URL of the Redis server. Default is `localhost`.
|
||||
- `REDIS_PORT`: The port of the Redis server. Default is `6379`.
|
||||
- `REDIS_DATABASE`: The database number to use. Default is `0`.
|
||||
- `HTTP_PORT`: The port to run the HTTP server on. Default is `9501`.
|
||||
```shell
|
||||
docker run --rm -it -p 9501:9501 scr.siteworxpro.com/traefik-api:v1.1.0
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Get All Routes
|
||||
```http request
|
||||
GET http://localhost:9501/http/routes
|
||||
Accept: application/json
|
||||
```
|
||||
```json
|
||||
[
|
||||
"route-1",
|
||||
"route-2"
|
||||
]
|
||||
```
|
||||
|
||||
### Get a Route
|
||||
```http request
|
||||
GET http://localhost:9501/http/routes/route-1
|
||||
Accept: application/json
|
||||
```
|
||||
```json
|
||||
{
|
||||
"id": "route-1",
|
||||
"rule": "Host(`example.com`)",
|
||||
"service": "service-1",
|
||||
"middlewares": [
|
||||
"middleware-1"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Dev Environment
|
||||
|
||||
### Prerequisites
|
||||
- Docker
|
||||
- Docker Compose
|
||||
|
||||
### Starting the Runtime
|
||||
```shell
|
||||
export PHP_IDE_CONFIG=serverName=localhost
|
||||
docker-compose up -d
|
||||
```
|
||||
### Start the server
|
||||
```shell
|
||||
docker exec -it traefik-redis-api-dev-runtime-1 rr serve
|
||||
```
|
||||
|
||||
You can access the api at `http://localhost:9501/`
|
||||
|
||||
### Xdebug
|
||||
|
||||
xdebug needs to be built into the container before it will work
|
||||
```shell
|
||||
docker exec -it traefik-redis-api-dev-runtime-1 bin/xdebug.sh
|
||||
```
|
||||
|
||||
### Install the dependencies
|
||||
```shell
|
||||
docker run --rm -v $(PWD):/app siteworxpro/composer install --ignore-platform-reqs
|
||||
```
|
||||
|
||||
### Running all tests
|
||||
```shell
|
||||
docker run --rm -v $(PWD):/app siteworxpro/composer run tests:all
|
||||
```
|
||||
### migrations
|
||||
create a new migration
|
||||
```shell
|
||||
docker run --rm -v $(PWD):/app siteworxpro/migrate:v4.18.3 create -ext sql -dir /app/db/migrations -seq create_users_table
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
|
||||
```text
|
||||
postgres://siteworxpro:password@localhost:5432/siteworxpro?sslmode=disable
|
||||
```
|
||||
Copyright (c)2025 Siteworx Professionals, LLC
|
||||
|
||||
```shell
|
||||
docker run --rm -v $(PWD):/app siteworxpro/migrate:v4.18.3 -database "postgres://siteworxpro:password@localhost:5432/siteworxpro?sslmode=disable" -path /app/db/migrations up
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
documentation
|
||||
files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom
|
||||
the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
```
|
||||
@@ -1,10 +1,10 @@
|
||||
#volumes:
|
||||
# pgdata: {}
|
||||
volumes:
|
||||
redisdata: {}
|
||||
|
||||
services:
|
||||
dev-runtime:
|
||||
ports:
|
||||
- "8080:8080"
|
||||
- "9501:9501"
|
||||
volumes:
|
||||
- .:/app
|
||||
build:
|
||||
@@ -14,24 +14,12 @@ services:
|
||||
environment:
|
||||
PHP_IDE_CONFIG: serverName=localhost
|
||||
WORKERS: 1
|
||||
HTTP_PORT: 8080
|
||||
DEBUG: 1
|
||||
REDIS_HOST: 192.168.1.30
|
||||
REDIS_HOST: redis
|
||||
|
||||
# migrations:
|
||||
# image: siteworxpro/migrate:v4.18.3
|
||||
# restart: no
|
||||
# volumes:
|
||||
# - .:/app
|
||||
# command: "-database 'postgres://${DB_DATABASE-siteworxpro}:${DB_PASSWORD-password}@${DB_HOST-postgres}:5432/siteworxpro?sslmode=disable' -path /app/db/migrations up"
|
||||
#
|
||||
# postgres:
|
||||
# image: postgres:latest
|
||||
# environment:
|
||||
# POSTGRES_USER: ${DB_USERNAME:-siteworxpro}
|
||||
# POSTGRES_PASSWORD: ${DB_PASSWORD:-password}
|
||||
# POSTGRES_DB: ${DB_DATABASE:-siteworxpro}
|
||||
# ports:
|
||||
# - "5432:5432"
|
||||
# volumes:
|
||||
# - pgdata:/var/lib/postgresql/data
|
||||
redis:
|
||||
image: redis:latest
|
||||
ports:
|
||||
- "6379:6379"
|
||||
volumes:
|
||||
- redisdata:/data
|
||||
@@ -4,12 +4,28 @@ declare(strict_types=1);
|
||||
|
||||
namespace Siteworxpro\App\Controllers;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use League\Route\Http\Exception\NotFoundException;
|
||||
use Nyholm\Psr7\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Siteworxpro\App\Traefik\ProtocolEnum;
|
||||
|
||||
abstract class Controller implements ControllerInterface
|
||||
{
|
||||
|
||||
protected function protocolEnumFromRequest(ServerRequest $request): ProtocolEnum
|
||||
{
|
||||
$protocol = $request->getAttribute('protocol');
|
||||
|
||||
try {
|
||||
return ProtocolEnum::fromString($protocol);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
Log::error($e->getMessage());
|
||||
|
||||
return ProtocolEnum::HTTP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServerRequest $request
|
||||
* @return ResponseInterface
|
||||
|
||||
@@ -20,10 +20,14 @@ class MiddlewaresController extends Controller
|
||||
if ($request->getAttribute('id') !== null) {
|
||||
$name = $request->getAttribute('id');
|
||||
|
||||
return JsonResponseFactory::createJsonResponse(RedisClient::getMiddleware($name));
|
||||
return JsonResponseFactory::createJsonResponse(
|
||||
RedisClient::getMiddleware($name, $this->protocolEnumFromRequest($request))
|
||||
);
|
||||
}
|
||||
|
||||
return JsonResponseFactory::createJsonResponse(RedisClient::getAllMiddlewares());
|
||||
return JsonResponseFactory::createJsonResponse(
|
||||
RedisClient::getAllMiddlewares($this->protocolEnumFromRequest($request))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,7 +43,7 @@ class MiddlewaresController extends Controller
|
||||
return JsonResponseFactory::createJsonResponse(['error' => 'Middleware is invalid'], 400);
|
||||
}
|
||||
|
||||
RedisClient::createOrReplace($name, $data, EntityEnum::MIDDLEWARE);
|
||||
RedisClient::createOrReplace($name, $data, EntityEnum::MIDDLEWARE, $this->protocolEnumFromRequest($request));
|
||||
|
||||
return JsonResponseFactory::createJsonResponse(['message' => 'Middleware added successfully']);
|
||||
}
|
||||
@@ -55,7 +59,7 @@ class MiddlewaresController extends Controller
|
||||
return JsonResponseFactory::createJsonResponse(['error' => 'Middleware is invalid'], 400);
|
||||
}
|
||||
|
||||
RedisClient::deleteAllKeys($name, EntityEnum::MIDDLEWARE);
|
||||
RedisClient::deleteAllKeys($name, EntityEnum::MIDDLEWARE , $this->protocolEnumFromRequest($request));
|
||||
|
||||
return JsonResponseFactory::createJsonResponse(['message' => 'Middleware deleted successfully']);
|
||||
}
|
||||
|
||||
@@ -20,10 +20,14 @@ class RoutesController extends Controller
|
||||
if ($request->getAttribute('id') !== null) {
|
||||
$name = $request->getAttribute('id');
|
||||
|
||||
return JsonResponseFactory::createJsonResponse(RedisClient::getRouter($name));
|
||||
return JsonResponseFactory::createJsonResponse(
|
||||
RedisClient::getRouter($name, $this->protocolEnumFromRequest($request))
|
||||
);
|
||||
}
|
||||
|
||||
return JsonResponseFactory::createJsonResponse(RedisClient::getAllRouters());
|
||||
return JsonResponseFactory::createJsonResponse(
|
||||
RedisClient::getAllRouters($this->protocolEnumFromRequest($request))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,7 +47,12 @@ class RoutesController extends Controller
|
||||
return JsonResponseFactory::createJsonResponse(['error' => 'Rule is required'], 400);
|
||||
}
|
||||
|
||||
RedisClient::createOrReplace($name, $data, EntityEnum::ROUTER);
|
||||
RedisClient::createOrReplace(
|
||||
$name,
|
||||
$data,
|
||||
EntityEnum::ROUTER,
|
||||
$this->protocolEnumFromRequest($request)
|
||||
);
|
||||
|
||||
return JsonResponseFactory::createJsonResponse(['message' => 'Router created successfully']);
|
||||
}
|
||||
@@ -55,7 +64,11 @@ class RoutesController extends Controller
|
||||
{
|
||||
$name = $request->getAttribute('id');
|
||||
|
||||
RedisClient::deleteAllKeys($name, EntityEnum::ROUTER);
|
||||
RedisClient::deleteAllKeys(
|
||||
$name,
|
||||
EntityEnum::ROUTER,
|
||||
$this->protocolEnumFromRequest($request)
|
||||
);
|
||||
|
||||
return JsonResponseFactory::createJsonResponse(['message' => 'Router deleted successfully']);
|
||||
}
|
||||
@@ -70,7 +83,7 @@ class RoutesController extends Controller
|
||||
$data = $request->getParsedBody();
|
||||
|
||||
try {
|
||||
RedisClient::patchEntity($name, $data, EntityEnum::ROUTER);
|
||||
RedisClient::patchEntity($name, $data, EntityEnum::ROUTER, $this->protocolEnumFromRequest($request));
|
||||
} catch (\InvalidArgumentException) {
|
||||
return JsonResponseFactory::createJsonResponse(['error' => 'Router not found'], 404);
|
||||
}
|
||||
|
||||
@@ -20,10 +20,14 @@ class ServicesController extends Controller
|
||||
if ($request->getAttribute('id') !== null) {
|
||||
$name = $request->getAttribute('id');
|
||||
|
||||
return JsonResponseFactory::createJsonResponse(RedisClient::getService($name));
|
||||
return JsonResponseFactory::createJsonResponse(
|
||||
RedisClient::getService($name, $this->protocolEnumFromRequest($request))
|
||||
);
|
||||
}
|
||||
|
||||
return JsonResponseFactory::createJsonResponse(RedisClient::getAllServices());
|
||||
return JsonResponseFactory::createJsonResponse(
|
||||
RedisClient::getAllServices($this->protocolEnumFromRequest($request))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,7 +43,7 @@ class ServicesController extends Controller
|
||||
return JsonResponseFactory::createJsonResponse(['error' => 'loadbalancer is required'], 400);
|
||||
}
|
||||
|
||||
RedisClient::createOrReplace($name, $data, EntityEnum::SERVICE);
|
||||
RedisClient::createOrReplace($name, $data, EntityEnum::SERVICE, $this->protocolEnumFromRequest($request));
|
||||
|
||||
return JsonResponseFactory::createJsonResponse(['message' => 'Service updated successfully']);
|
||||
}
|
||||
@@ -55,7 +59,7 @@ class ServicesController extends Controller
|
||||
return JsonResponseFactory::createJsonResponse(['error' => 'Service name is required'], 400);
|
||||
}
|
||||
|
||||
RedisClient::deleteAllKeys($name, EntityEnum::SERVICE);
|
||||
RedisClient::deleteAllKeys($name, EntityEnum::SERVICE, $this->protocolEnumFromRequest($request));
|
||||
|
||||
return JsonResponseFactory::createJsonResponse(['message' => 'Service deleted successfully']);
|
||||
}
|
||||
|
||||
@@ -120,7 +120,10 @@ class Server
|
||||
*/
|
||||
protected function registerRoutes(): void
|
||||
{
|
||||
$this->router->group('/http/routes', function (RouteGroup $router) {
|
||||
$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');
|
||||
@@ -128,14 +131,14 @@ class Server
|
||||
$router->delete('/{id}', RoutesController::class . '::delete');
|
||||
});
|
||||
|
||||
$this->router->group('/http/services', function (RouteGroup $router) {
|
||||
$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('/http/middlewares', function (RouteGroup $router) {
|
||||
$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');
|
||||
|
||||
@@ -18,4 +18,14 @@ enum ProtocolEnum
|
||||
self::UDP => 'udp',
|
||||
};
|
||||
}
|
||||
|
||||
public static function fromString(string $value): self
|
||||
{
|
||||
return match ($value) {
|
||||
'http' => self::HTTP,
|
||||
'tcp' => self::TCP,
|
||||
'udp' => self::UDP,
|
||||
default => throw new \InvalidArgumentException("Invalid protocol: $value"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user