• Час читання ~2 хв
  • 17.03.2023

Як веб-розробникам, нам часто доводиться взаємодіяти з API з наших додатків Laravel. HTTP-клієнт Laravel, представлений у версії 7, забезпечує зручну та інтуїтивно зрозумілу обгортку навколо бібліотеки Guzzle HTTP. У цій статті ми розглянемо п'ять цінних трюків для роботи з клієнтом Laravel HTTP, які можуть зробити ваш досвід розробки більш ефективним і приємним.

Ці трюки включають використання макросів HTTP, налаштування HTTP-клієнта для контейнерних служб, конфігурацію портативної базової URL-адреси, запобігання випадковим запитам у тестах та прослуховування подій HTTP. Освоївши ці поради, ви можете впорядкувати взаємодію з API та створити більш надійні та ремонтопридатні програми Laravel.

HTTP Макроси

Багато служб Laravel мають функцію "макрос", яка дозволяє визначати користувацькі методи для вашої програми. Замість того, щоб розширювати основні класи з Laravel Framework, ви можете додати ці макроси до boot() методу в постачальника послуг.

У документах HTTP показано приклад макросу, який можна використовувати для визначення загальних параметрів:

public function boot(): void
{
    Http::macro('github', function () {
        return Http::withHeaders([
            'X-Example' => 'example',
        ])->baseUrl('https://github.com');
    });
}
// Usage
response = Http::github()->get('/');

Макроси можуть визначати будь-які зручні методи, які потрібно визначити та повторно використовувати у вашій програмі. Приклад документації макросів торкається ще однієї поради щодо налаштування HTTP-клієнтів для використання в інших службах.

Ми ще раз переглянемо об'єднання макросів з передачею клієнтів в інші контейнерні сервіси в наступному розділі.

Налаштуйте HTTP-клієнт для контейнерних служб

Під час взаємодії з API з програми Laravel вам, швидше за все, знадобляться різні налаштовувані параметри для клієнта. Наприклад, якщо API має кілька середовищ, вам знадобиться налаштовувана базова URL-адреса, токен, налаштування тайм-ауту тощо.

Ми можемо використовувати макрос для визначення клієнта, представляти клієнта як власну послугу, яку ми можемо, вводити в інші послуги або трохи обох.

Спочатку давайте розглянемо визначення налаштувань клієнта в методі постачальника register() послуг:

public function register(): void
{
    $this->app->singleton(ExampleService::class, function (Application $app) {
        $client = Http::withOptions([
            'base_uri' => config('services.example.base_url'),
            'timeout' => config('services.example.timeout', 10),
            'connect_timeout' => config('services.example.connect_timeout', 2),
        ])->withToken(config('services.example.token'));

        return new ExampleService($client);
    });
}

У визначенні послуги singleton ми об'єднали кілька дзвінків, щоб налаштувати клієнта. В результаті ми можемо передати нашому конструктору послуг, наприклад: Служба використовує withOptions() метод для безпосереднього налаштування параметрів Guzzle, але ми PendingRequest також могли б використовувати деякі методи зручності, надані клієнтом HTTP:Або, якщо ви хочете об'єднати макроси зі службами, ви можете використовувати макроси, визначені в методі boot() вашого AppServiceProvider:

class ExampleService
{
    public function __construct(
        private PendingRequest $client
    ) {}
    public function getWidget(string $uid)
    {
        $response = $this->client
            ->withUrlParameters(['uid' => $uid])
            ->get('widget/{uid}');

        return new Widget($response->json());
    }
}

$this->app->singleton(ExampleService::class, function (Application $app) {
    $client = Http::baseUrl(config('services.example.base_url'))
        ->timeout(config('services.example.timeout', 10))
        ->connectTimeout(config('services.example.connect_timeout', 2))
        ->withToken(config('services.example.token'));

    return new ExampleService($client);
});

$this->app->singleton(ExampleService::class, function (Application $app) {
    return new ExampleService(Http::github());
});

Портативна конфігурація базової URL-адреси

Можливо, ви бачили, що базова URL-адреса за замовчуванням включала слідування/, оскільки вона забезпечує найбільшу портативність у моєму варіанті, згідно з RFC 3986.

Візьмемо наступний приклад конфігурації служби (зверніть увагу на base_url за замовчуванням):

eturn [
    'example' => [
        'base_url' => env('EXAMPLE_BASE_URI', 'https://api.example.com/v1/'),
        'token' => env('EXAMPLE_SERVICE_TOKEN'),
        'timeout' => env('EXAMPLE_SERVICE_TIMEOUT', 10),
        'connect_timeout' => env('EXAMPLE_SERVICE_TIMEOUT', 2),
    ],
];

Якщо наш API має префікс /v1/ шляху у виробництві та в постановці, можливо, це просто https://stg-api.example.com/; використання скісної риски змушує URL-адреси працювати належним чином без змін коду. У тандемі з налаштуванням трейлінгу /зверніть увагу, що всі виклики API в моєму коді використовують відносні шляхи:

$this->client
    ->withUrlParameters(['uid' => $uid])
    // Example:
    // Staging - https://stg-api.example.com/widget/123
    // Production - https://api.example.com/v1/widget/123
    ->get('widget/{uid}');

Дивіться створення Guzzle клієнтської документації, щоб побачити, як різні стилі base_uri впливають на те, як вирішуються URI.

Запобігання бродячим запитам у тестах HTTP-клієнт Laravel надає чудові інструменти тестування, щоб полегшити написання тестів

. Коли я пишу код, який взаємодіє з API, мені неприємно, що в моїх тестах якимось чином відбуваються фактичні мережеві запити. Введіть запобігання бродячим запитам за допомогою HTTP-клієнта Laravel:

Http::preventStrayRequests();

Http::fake([
    'github.com/*' => Http::response('ok'),
]);
// Run test code
// If any other code triggers an HTTP call via Laravel's client
// an exception is thrown.

На мою думку, найкращий спосіб використання preventStrayRequests() - це визначення методу в тестових setUp() класах, які ви очікуєте взаємодіяти з API. Можливо, ви також можете додати його до базового TestCase класу вашої програми:

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Support\Facades\Http;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;

    public function setUp(): void
    {
        parent::setUp();

        Http::preventStrayRequests();
    }
}

Це гарантує, що кожен дзвінок клієнта HTTP, ініційований у вашому тестовому наборі, матиме підроблений запит, який створює його резервну копію. Використання цього методу дає мені величезний приріст впевненості в тому, що я покрив усі свої вихідні запити у своїх тестах еквівалентною підробкою.

Обробники реєстрації для HTTP-клієнта HTTP Events

Laravel мають цінні події, які ви можете використовувати для швидкого використання основних етапів життєвого циклу запиту/відповіді. На момент написання статті звільнено три події:

  • Illuminate\Http\Client\Events\RequestSending

Illuminate\Http\Client\Events\ResponseReceivedIlluminate\Http\Client\Events\ConnectionFailedСкажімо, ви хочете візуалізувати кожну URL-адресу, на яку ваша програма робить запити. Ми могли б легко скористатися RequestSending подією та вийти з кожного запиту:Щоб змусити обробника подій працювати, додайте наступне до EventServiceProvider класу:Після того, як все це буде підключено, ви побачите щось на зразок наступного у своєму журналі для кожного запиту, зробленого за допомогою HTTP-клієнта:

namespace App\Listeners;

use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;

class LogRequestSending
{
    public function handle(object $event): void
    {
        Log::debug('HTTP request is being sent.', [
            'url' => $event->request->url(),
        ]);
    }
}

use App\Listeners\LogRequestSending;
use Illuminate\Http\Client\Events\RequestSending;
// ...
protected $listen = [
    Registered::class => [
        SendEmailVerificationNotification::class,
    ],
    RequestSending::class => [
        LogRequestSending::class,
    ],
];

[2023-03-17 04:06:03] local.DEBUG: HTTP request is being sent. {"url":"https://api.example.com/v1/widget/123"}

Дізнайтеся більше

В офіційній документації Laravel HTTP є все необхідне для початку роботи. Сподіваюся, цей підручник дав вам натхнення та хитрощі, які ви можете використовувати у своїх програмах Laravel

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Про автора CrazyBoy49z
WORK EXPERIENCE
Контакти
Ukraine, Lutsk
+380979856297