Шлюз в PHP

RedDeveloper
25.01.2023 10:51
Шлюз в PHP

Что делает API-шлюз?

API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.

API Gateway получает клиентские запросы, направляет их в соответствующий микросервис, а затем возвращает ответ сервера клиенту.

Шлюз отвечает за такие задачи, как маршрутизация, аутентификация и ограничение скорости. Это позволяет микросервисам сосредоточиться на своих индивидуальных задачах и повышает общую производительность и масштабируемость системы.

Тогда мы можем сказать в двух словах: "API-шлюз - это инструмент управления API, который находится между клиентом и набором бэкенд-сервисов".

Зачем использовать API-шлюз?

Тогда мы можем сказать в двух словах "API-шлюз - это инструмент управления API которыйЭто изображение использовано из поиска google

Большинство корпоративных API развертываются через API-шлюзы. Обычно API-шлюзы выполняют общие задачи, которые используются в системе API-сервисов, такие как аутентификация пользователей, ограничение скорости и статистика.

В самом простом виде API-сервис принимает удаленный запрос и возвращает ответ. Но в реальной жизни все не так просто. Рассмотрим различные проблемы, возникающие при размещении крупномасштабных API.

  • Вы хотите защитить API от чрезмерного использования и злоупотреблений, поэтому вы используете службу аутентификации и ограничение скорости.
  • хотите понять, как люди используют ваши API, поэтому вы добавили инструменты аналитики и мониторинга.
  • Если у вас есть монетизированные API, вы захотите подключиться к биллинговой системе.
  • Возможно, вы перешли на архитектуру микросервисов, в этом случае один запрос может потребовать обращения к десяткам отдельных приложений.
  • Со временем вы добавите несколько новых API-сервисов и уберете другие, но ваши клиенты все равно захотят найти все ваши сервисы в одном месте.

Сложность заключается в том, чтобы предложить вашим клиентам простой и надежный опыт работы в условиях всей этой сложности. API-шлюз - это способ отделить клиентский интерфейс от реализации бэкенда. Когда клиент делает запрос, API-шлюз разбивает его на несколько запросов, направляет их в нужные места, выдает ответ и все отслеживает.

является самым популярным API-шлюзом:

𝗥𝗼𝘂𝘁𝗶𝗻𝗴: API-шлюз получает запросы от клиентов и направляет их в соответствующий микросервис. Это позволяет клиентам получать доступ к различным микросервисам через единую точку входа, упрощая общий дизайн системы.

𝗦𝗲𝗰𝘂𝗿𝗶𝘁𝘆 API-шлюз может использоваться для аутентификации клиентов и применения политик контроля доступа к микросервисам. Это помогает обеспечить доступ к микросервисам только авторизованным клиентам и предотвратить несанкционированный доступ.

𝐓𝐫𝐚𝐧𝐬𝐟𝐨𝐫𝐦𝗶𝗻𝗴 𝐫𝐞𝐪𝐮𝐞𝐬𝐭𝐬 𝐚𝐧𝐝 𝐫𝐞𝐬𝐩𝐨𝐧𝐬𝐞𝐬: API Gateway может преобразовывать входящие запросы и исходящие ответы на бэкенд и из бэкенда для удовлетворения потребностей различных клиентов или соответствия различным архитектурам бэкенда.

𝗥𝗮𝘁𝗲𝗹𝗶𝗺𝗶𝘁𝗶𝗻𝗴: Вы можете ограничить доступ клиентов к микросервисам с помощью шлюза API. Это поможет предотвратить атаки типа "отказ в обслуживании" и другие виды вредоносного поведения.

𝗟𝗼𝗮𝗱𝗯𝗮𝗹𝗮𝗻𝗰𝗶𝗻𝗴: API Gateway может распределять входящие запросы между несколькими экземплярами микросервиса, позволяя системе обрабатывать большее количество запросов и повышая общую производительность и масштабируемость.

𝗖𝗮𝗰𝗵𝗶𝗻𝗴: Шлюз API может кэшировать ответы микросервисов, уменьшая количество запросов, которые необходимо перенаправлять микросервисам, и повышая общую производительность системы.

𝗦𝗲𝗿𝘃𝗲𝗿𝗹𝗲𝘀𝘀𝗲𝘅𝗲𝗰𝘂𝘁𝗶𝗼𝗻: API Gateway может интегрироваться с другими сервисами, такими как AWS Lambda, для создания бессерверных архитектур и обеспечения сложной обработки запросов без необходимости использования выделенного сервера.

𝗖𝗶𝗿𝗰𝘂𝗶𝘁 𝗯𝗿𝗲𝗮𝗸𝗲𝗿: API Gateway можно использовать для реализации схем автоматического выключателя, что поможет защитить от каскадных сбоев и повысить отказоустойчивость вашей системы.

𝗥𝗲𝘃𝗲𝗿𝘀𝗲𝗽𝗿𝗼𝘅𝘆: API Gateway может действовать как обратный прокси-сервер, направляя входящие запросы в соответствующую внутреннюю службу на основе пути запроса или других критериев.

𝗔𝗣𝗜 𝘃𝗲𝗿𝘀𝗶𝗼𝗻𝗶𝗻𝗴: API Gateway можно использовать для реализации версионности API, что позволяет поддерживать несколько версий API и управлять переходом от одной версии к другой.

Реализация

Попытаюсь объяснить на базовом примере для API.

Допустим, у вас есть 3 микросервиса:

  1. Пользователи
  2. Посты
  3. Ядро

Я предполагаю, что вы используете http Only cookie для хранения токена пользователя.

В микросервисе Core у меня такая структура маршрута:

Route::prefix('core')->group(function () {
    Route::post('register', [AuthController::class, 'register']);
    Route::post('login', [AuthController::class, 'login']);

    Route::middleware('scope.trader')->group(function () {
        Route::get('user', [AuthController::class, 'user']);

    });
});

Я хочу войти в систему, для чего мне нужно отправить запрос API, и я должен придумать решение для отправки токена в любое время, когда он мне понадобится.

  1. login (именно здесь вы получаете токен) и register не нуждаются в токене
  2. пользователю нужен токен (вот где вы просили решение)

Итак, в дополнение к получению результата, я должен создать сервис для пользователя, и вот как я это сделал:

UserService :
class UserService extends ApiService
{
    public function __construct()
    {
        // Get User Endpoint Microservice API URL
        $this->endpoint = env('USERS_MS') . '/api';
    }
}
ApiService :
abstract class ApiService
{
    protected string $endpoint;

    public function request($method, $path, $data = [])
    {
        $response = $this->getRequest($method, $path, $data);

        if ($response->ok()) {return $response->json();};

        throw new HttpException($response->status(), $response->body());
    }

    public function getRequest($method, $path, $data = [])
    {
        return \Http::acceptJson()->withHeaders([
            'Authorization' =>  'Bearer ' . request()->cookie('token')
        ])->$method("{$this->endpoint}/{$path}", $data);
    }

    public function post($path, $data)
    {
        return $this->request('post', $path, $data);
    }

    public function get($path)
    {
        return $this->request('get', $path);
    }

    public function put($path, $data)
    {
        return $this->request('put', $path, $data);
    }

    public function delete($path)
    {
        return $this->request('delete', $path);
    }
}

'попытаюсь объяснить на базовом примере для API.

Допустим, у вас есть 3 микросервиса:

  1. Пользователи
  2. Посты
  3. Ядро

Я предполагаю, что вы используете httpOnly cookie для хранения токена пользователя.

В микросервисе Core у меня такая структура маршрута:

Route::prefix('core')->group(function () {
    Route::post('register', [AuthController::class, 'register']);
    Route::post('login', [AuthController::class, 'login']);
    Route::middleware('scope.trader')->group(function () {
        Route::get('user', [AuthController::class, 'user']);
    });
});

Я хочу войти в систему, для чего мне нужно отправить запрос API, и я должен придумать решение для отправки токена в любое время, когда он мне понадобится.

  1. login (именно здесь вы получаете токен) и register не нуждаются в токене
  2. пользователю нужен токен (вот где вы просили решение)

Поэтому, чтобы получить результат, я должен создать сервис для пользователя, и вот как я это сделал:

UserService :
class UserService extends ApiService
{
    public function __construct()
    {
        // Get User Endpoint Microservice API URL
        $this->endpoint = env('USERS_MS') . '/api';
    }
}
ApiService :
abstract class ApiService
{
    protected string $endpoint;
    public function request($method, $path, $data = [])
    {
        $response = $this->getRequest($method, $path, $data);
        if ($response->ok()) {return $response->json();};
        throw new HttpException($response->status(), $response->body());
    }
    public function getRequest($method, $path, $data = [])
    {
        return \Http::acceptJson()->withHeaders([
            'Authorization' =>  'Bearer ' . request()->cookie('token')
        ])->$method("{$this->endpoint}/{$path}", $data);
    }
    public function post($path, $data)
    {
        return $this->request('post', $path, $data);
    }
    public function get($path)
    {
        return $this->request('get', $path);
    }
    public function put($path, $data)
    {
        return $this->request('put', $path, $data);
    }
    public function delete($path)
    {
        return $this->request('delete', $path);
    }
}

Если вам интересно, откуда взялся этот UserService, то я должен сказать, что я создал пакет для использования его в других микросервисах, так что вы можете сделать то же самое или просто создать сервис и использовать его в своих микросервисах или т.д.

Про ApiService все очевидно, но я постараюсь объяснить основу.

  1. мы хотим сделать вызов API, мы можем просто вызвать методы Allowed в этом классе, затем наши методы будут вызывать запросы, чтобы передать общие аргументы, и в конечном итоге использовать эти аргументы для выполнения вызова API.
  2. метод выполняет вызов и получает сохраненный токен из куки httpOnly, и отправляет его в качестве заголовка Authorization конечной точке, и в итоге возвращает все, что получил от цели.

Итак, если мы хотим использовать это, мы можем просто сделать вот так в нашем контроллере:

class AuthController extends Controller
{
    // use Services\UserService;
    public UserService $userService;

    /**
     * @param UserService $userService
     */
    public function __construct(UserService $userService)
    {
        $this->userService = $userService;
    }

    public function register(RegisterRequest $request)
    {
        $data = $request->only('name', 'email', 'password') + ['additional_fileds' => 0 ];
        // additional fields can be used for something except from request and
        // optional, like is it admin or user or etc.

        // call the post method, pass the endpoint url(`register`), pass $data
        $user = $this->userService->post('register', $data);
        // get data from target endpoint
        // and ...
        return response($user, Response::HTTP_CREATED);
    }

    public function login(Request $request)
    {
        // same thing here again, but this time i passed scope to help me
        // get the specific user scope
        $data = $request->only('email', 'password') + ['scope' => 'writer'];

        $response = $this->userService->post('login', $data);
        // as you can see when user do success login, we will get token,
        // which i got that token using Passport and set it to $cookie
        $cookie = cookie('token', $response['token'], 60 * 24); // 1 day
      
        // then will set a new httpOnly token on response.
        return response([
            'message' => 'success'
        ])->withCookie($cookie);
    }

    public function user(Request $request)
    {
        // Here, base on userService as you saw, we passed token in all requests
        // which if token exist, we get the result, since we're expecting
        // token to send back the user informations.

        $user = $this->userService->get('user');

        // get posts belong to authenticated user
        $posts = Post::where('user_id', $user['id'])->get();

        $user['posts'] = $posts;

        return $user;
    }
}

'попытаюсь объяснить на базовом примере для API.

Допустим, у вас есть 3 микросервиса:

  1. Пользователи
  2. Посты
  3. Ядро

Я предполагаю, что вы используете httpOnly cookie для хранения токена пользователя.

В микросервисе Core у меня такая структура маршрута:

Route::prefix('core')->group(function () {
    Route::post('register', [AuthController::class, 'register']);
    Route::post('login', [AuthController::class, 'login']);
    Route::middleware('scope.trader')->group(function () {
        Route::get('user', [AuthController::class, 'user']);
    });
});

Я хочу войти в систему, для чего мне нужно отправить запрос API, и я должен придумать решение для отправки токена в любое время, когда он мне понадобится.

  1. login (здесь вы получаете токен) и register не нуждаются в токене
  2. пользователю нужен токен (именно здесь вы просили решение)

Итак, чтобы получить результат, я должен создать сервис для пользователя, и вот как я это сделал:

UserService :
class UserService extends ApiService
{
    public function __construct()
    {
        // Get User Endpoint Microservice API URL
        $this->endpoint = env('USERS_MS') . '/api';
    }
}
ApiService :
abstract class ApiService
{
    protected string $endpoint;
    public function request($method, $path, $data = [])
    {
        $response = $this->getRequest($method, $path, $data);
        if ($response->ok()) {return $response->json();};
        throw new HttpException($response->status(), $response->body());
    }
    public function getRequest($method, $path, $data = [])
    {
        return \Http::acceptJson()->withHeaders([
            'Authorization' =>  'Bearer ' . request()->cookie('token')
        ])->$method("{$this->endpoint}/{$path}", $data);
    }
    public function post($path, $data)
    {
        return $this->request('post', $path, $data);
    }
    public function get($path)
    {
        return $this->request('get', $path);
    }
    public function put($path, $data)
    {
        return $this->request('put', $path, $data);
    }
    public function delete($path)
    {
        return $this->request('delete', $path);
    }
}

Вы задаетесь вопросом, откуда взялся этот UserService, то я должен сказать, что я создал пакет для использования его в других микросервисах, так что вы можете сделать то же самое или просто создать сервис и использовать его в своих микросервисах или т.д.

Про ApiService все очевидно, но я постараюсь объяснить основу.

  1. мы хотим сделать вызов API, мы можем просто вызвать методы Allowed в этом классе, затем наши методы вызовут request, чтобы передать общие аргументы, и, в конечном итоге, используя эти аргументы, сделать вызов API.
  2. метод выполняет вызов и получает сохраненный токен из куки httpOnly, и отправляет его в качестве заголовка Authorization в целевую конечную точку, и в итоге возвращает все, что получил от цели.

Итак, если мы хотим использовать это, мы можем просто сделать вот так в нашем контроллере:

class AuthController extends Controller
{
    // use Services\UserService;
    public UserService $userService;
    /**
     * @param UserService $userService
     */
    public function __construct(UserService $userService)
    {
        $this->userService = $userService;
    }
    public function register(RegisterRequest $request)
    {
        $data = $request->only('name', 'email', 'password') + ['additional_fileds' => 0 ];
        // additional fields can be used for something except from request and
        // optional, like is it admin or user or etc.
        // call the post method, pass the endpoint url(`register`), pass $data
        $user = $this->userService->post('register', $data);
        // get data from target endpoint
        // and ...
        return response($user, Response::HTTP_CREATED);
    }
    public function login(Request $request)
    {
        // same thing here again, but this time i passed scope to help me
        // get the specific user scope
        $data = $request->only('email', 'password') + ['scope' => 'writer'];
        $response = $this->userService->post('login', $data);
        // as you can see when user do success login, we will get token,
        // which i got that token using Passport and set it to $cookie
        $cookie = cookie('token', $response['token'], 60 * 24); // 1 day
      
        // then will set a new httpOnly token on response.
        return response([
            'message' => 'success'
        ])->withCookie($cookie);
    }
    public function user(Request $request)
    {
        // Here, base on userService as you saw, we passed token in all requests
        // which if token exist, we get the result, since we're expecting
        // token to send back the user informations.
        $user = $this->userService->get('user');
        // get posts belong to authenticated user
        $posts = Post::where('user_id', $user['id'])->get();
        $user['posts'] = $posts;
        return $user;
    }
}

Как насчет пользовательского микросервиса? Ну, здесь все ясно, и он должен работать как базовое приложение.

Вот маршруты:

Route::post('register', [AuthController::class, 'register']);
Route::post('login', [AuthController::class, 'login']);

Route::middleware(['bunch','of', 'middlewares'])->group( function (){
    Route::get('user', [AuthController::class, 'user']);
});

А в контроллере :

class AuthController extends Controller
{
    public function register(Request $request)
    {
        $user = User::create(
            $request->only('first_name', 'email', 'additional_field')
            + ['password' => \Hash::make($request->input('password'))]
        );

        return response($user, Response::HTTP_CREATED);
    }


    public function login(Request $request)
    {
        if (!\Auth::attempt($request->only('email', 'password'))) {
            return response([
                'error' => 'user or pass is wrong or whatever.'
            ], Response::HTTP_UNAUTHORIZED);
        }

        $user = \Auth::user();

        $jwt = $user->createToken('token', [$request->input('here you can pass the required scope like trader as i expalined in top')])->plainTextToken;

        return compact('token');
    }

    public function user(Request $request)
    {
        return $request->user();
    }
}

Итак, вот полный пример, и вы можете использовать подход микросервиса Core на других микросервисах для получения информации, связанной с аутентифицированным пользователем, и, как вы видите, все будет аутентифицировано благодаря этим запросам от ядра к другим микросервисам.

Мой список статей в Publis

Руководство для начинающих по веб-разработке на React.js
Руководство для начинающих по веб-разработке на React.js

21.03.2023 12:23

Веб-разработка - это захватывающая и постоянно меняющаяся область, которая постоянно развивается благодаря новым технологиям и тенденциям. Одним из самых популярных фреймворков для веб-разработки сегодня является React.js. Если вы начинающий веб-разработчик и хотите узнать больше о React.js, это...

Разница между Angular и React
Разница между Angular и React

21.03.2023 07:56

React и AngularJS - это два самых популярных фреймворка для веб-разработки. Оба фреймворка имеют свои уникальные особенности и преимущества, которые делают их подходящими для различных проектов веб-разработки.

Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit

20.03.2023 14:01

Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а также новые инструменты веб-скраппинга с открытым исходным кодом для их обхода.

Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра

20.03.2023 12:24

Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие действия:

ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023

20.03.2023 11:15

О тренинге HTML JavaScript :HTML (язык гипертекстовой разметки) и CSS (каскадные таблицы стилей) - две основные технологии для создания веб-страниц. HTML обеспечивает структуру страницы CSS (визуальное и звуковое) оформление для различных устройств. Наряду с графикой и сценариями HTML и CSS являются...

Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular

20.03.2023 08:46

Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?