Реализация API Gateway в Laravel

от автора

в
Время чтения: 4 мин.

API Gateway — это шаблон проектирования, который служит единой точкой входа для всех клиентских запросов к вашей системе микросервисов или модульному приложению. Вот как можно реализовать API Gateway в Laravel:

1. Установка и настройка базового проекта

Создайте новый проект Laravel:

composer create-project laravel/laravel api-gateway

2. Основные компоненты API Gateway

Маршрутизация запросов

В файле routes/api.php определите маршруты, которые будет обрабатывать шлюз:

use Illuminate\Support\Facades\Http;
use Illuminate\Http\Request;

Route::prefix('v1')->group(function () {
    // Маршрут для сервиса пользователей
    Route::prefix('users')->group(function () {
        Route::get('/', function (Request $request) {
            return Http::get('http://user-service/api/v1/users')->json();
        });

        Route::get('/{id}', function (Request $request, $id) {
            return Http::get("http://user-service/api/v1/users/{$id}")->json();
        });
    });

    // Маршрут для сервиса заказов
    Route::prefix('orders')->group(function () {
        Route::get('/', function (Request $request) {
            return Http::get('http://order-service/api/v1/orders')->json();
        });
    });
});

3. Проксирование запросов

Создайте middleware для обработки проксирования:

php artisan make:middleware ProxyMiddleware

В файле app/Http/Middleware/ProxyMiddleware.php:

public function handle(Request $request, Closure $next, $service)
{
    $services = [
        'user' => 'http://user-service/api',
        'order' => 'http://order-service/api',
        'product' => 'http://product-service/api',
    ];

    if (!array_key_exists($service, $services)) {
        abort(404, 'Service not found');
    }

    $response = Http::withHeaders($request->header())
        ->baseUrl($services[$service])
        ->{$request->method()}(
            $request->path(),
            $request->method() === 'GET' ? $request->query() : $request->all()
        );

    return response($response->body(), $response->status())
        ->withHeaders($response->headers());
}

Зарегистрируйте middleware в app/Http/Kernel.php:

protected $routeMiddleware = [
    'proxy' => \App\Http\Middleware\ProxyMiddleware::class,
];

Теперь можно использовать в маршрутах:

Route::any('/{service}/{path}', function ($service, $path) {
    // Все будет обработано middleware
})->where('path', '.*')->middleware('proxy:' . $service);

4. Аутентификация и авторизация

Создайте middleware для проверки JWT токенов:

php artisan make:middleware AuthenticateGateway

Реализация:

public function handle(Request $request, Closure $next)
{
    $token = $request->bearerToken();

    if (!$token) {
        return response()->json(['error' => 'Unauthorized'], 401);
    }

    try {
        $response = Http::withHeaders([
            'Authorization' => 'Bearer ' . $token
        ])->get('http://auth-service/api/validate-token');

        if (!$response->successful()) {
            throw new \Exception('Invalid token');
        }

        $request->merge(['user' => $response->json()]);

    } catch (\Exception $e) {
        return response()->json(['error' => 'Unauthorized'], 401);
    }

    return $next($request);
}

5. Кеширование ответов

Используйте кеширование для часто запрашиваемых данных:

Route::get('/products', function () {
    return Cache::remember('products', 3600, function () {
        return Http::get('http://product-service/api/products')->json();
    });
});

6. Логирование запросов

Создайте middleware для логирования:

public function handle(Request $request, Closure $next)
{
    $start = microtime(true);

    $response = $next($request);

    $log = [
        'method' => $request->method(),
        'path' => $request->path(),
        'status' => $response->status(),
        'duration' => microtime(true) - $start,
        'ip' => $request->ip(),
        'user_agent' => $request->userAgent(),
        'timestamp' => now()->toDateTimeString(),
    ];

    Log::channel('gateway')->info(json_encode($log));

    return $response;
}

7. Обработка ошибок

В app/Exceptions/Handler.php:

public function render($request, Throwable $exception)
{
    if ($exception instanceof ConnectionException) {
        return response()->json([
            'error' => 'Service unavailable',
            'message' => 'The requested service is currently unavailable'
        ], 503);
    }

    return parent::render($request, $exception);
}

8. Конфигурация сервисов

В .env добавьте адреса сервисов:

USER_SERVICE_URL=http://user-service
ORDER_SERVICE_URL=http://order-service
PRODUCT_SERVICE_URL=http://product-service
AUTH_SERVICE_URL=http://auth-service

9. Дополнительные возможности

Ограничение запросов (Rate Limiting)

Route::middleware(['throttle:60,1'])->group(function () {
    Route::get('/users', function () {
        // ...
    });
});

Валидация запросов

Route::post('/orders', function (Request $request) {
    $validated = $request->validate([
        'product_id' => 'required|integer',
        'quantity' => 'required|integer|min:1',
    ]);

    return Http::post('http://order-service/api/orders', $validated)->json();
});

Документация API

Используйте пакеты типа Laravel OpenAPI для генерации документации.

Заключение

Это базовая реализация API Gateway в Laravel. Для production-окружения рассмотрите:

  1. Использование специализированных решений (Kong, Apigee, KrakenD)
  2. Добавление механизма circuit breaker
  3. Реализацию балансировки нагрузки между экземплярами сервисов
  4. Более сложную систему мониторинга и логирования
  5. Кеширование на уровне шлюза

Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Сколько будет 10 + 5?