• Czas czytania ~6 min
  • 17.03.2023

Jako twórcy stron internetowych często musimy wchodzić w interakcje z interfejsami API z naszych aplikacji Laravel. Klient HTTP Laravel, wprowadzony w wersji 7, zapewnia wygodne i intuicyjne opakowanie wokół biblioteki HTTP Guzzle. W tym artykule omówimy pięć cennych sztuczek do pracy z klientem HTTP Laravel, które mogą sprawić, że Twoje środowisko programistyczne będzie bardziej wydajne i przyjemne.

Te sztuczki obejmują używanie makr HTTP, konfigurowanie klienta HTTP dla usług kontenerów, konfigurację przenośnego podstawowego adresu URL, zapobieganie błędnym żądaniom w testach i nasłuchiwanie zdarzeń HTTP. Opanowując te wskazówki, możesz usprawnić interakcje z interfejsem API i tworzyć bardziej niezawodne i łatwe w utrzymaniu aplikacje Laravel.

Makra

HTTP Wiele usług Laravel ma funkcję "makr", która pozwala zdefiniować niestandardowe metody dla aplikacji. Zamiast rozszerzać klasy podstawowe z Laravel Framework, można dodać te makra do boot() metody u usługodawcy.

Dokumentacja HTTP pokazuje przykład makra, którego można użyć do zdefiniowania typowych ustawień:

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

Makra mogą definiować dowolne wygodne metody, które chcesz zdefiniować i ponownie użyć w aplikacji. Przykład dokumentacji makr zawiera inną wskazówkę dotyczącą konfigurowania klientów HTTP do użytku w innych usługach.

W następnej sekcji ponownie przyjrzymy się łączeniu makr z przekazywaniem klientów do innych usług kontenerowych.

Konfigurowanie klienta HTTP dla usług

kontenerów Podczas interakcji z interfejsami API z aplikacji Laravel prawdopodobnie będziesz potrzebować różnych konfigurowalnych ustawień dla klienta. Jeśli na przykład interfejs API ma wiele środowisk, będziesz potrzebować konfigurowalnego podstawowego adresu URL, tokenu, ustawień limitu czasu i innych.

Możemy wykorzystać makro do zdefiniowania klienta, przedstawić klienta jako jego własną usługę, którą możemy, wprowadzić inne usługi lub trochę obu.

Najpierw przyjrzyjmy się definiowaniu ustawień klienta w metodzie register() usługodawcy:

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);
    });
}

W definicji usługi singleton połączyliśmy kilka wywołań, aby skonfigurować klienta. Rezultatem jest instancja, którą możemy przekazać do naszego konstruktora PendingRequest usług w następujący sposób:Usługa używa tej withOptions() metody do bezpośredniego konfigurowania opcji Guzzle, ale mogliśmy również użyć pewnych wygodnych metod dostarczanych przez klienta HTTP:Lub, jeśli chcesz połączyć makra z usługami, możesz użyć makr zdefiniowanych w metodzie AppServiceProviderboot():

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());
});

Konfiguracja

przenośnego podstawowego adresu URL Być może widziałeś, że domyślny podstawowy adres URL zawiera końcowy, ponieważ zapewnia on największą przenośność w mojej opcji, / zgodnie z RFC 3986.

Weźmy następującą przykładową konfigurację usługi (zwróć uwagę na domyślną 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),
    ],
];

Jeśli nasz interfejs API ma prefiks /v1/ ścieżki w środowisku produkcyjnym i przejściowym, być może jest to po prostu https://stg-api.example.com/; użycie końcowego ukośnika powoduje, że adresy URL działają zgodnie z oczekiwaniami bez zmian w kodzie. W połączeniu z konfigurowaniem końcowych /, zauważ, że wszystkie wywołania API w moim kodzie używają względnych ścieżek:

$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}');

Zobacz Guzzle's creating a client documentation, aby zobaczyć, jak różne style base_uri wpływają na sposób rozpoznawania identyfikatorów URI.

Zapobieganie błędnym żądaniom w testach Klient HTTP firmy Laravel zapewnia doskonałe narzędzia do testowania

, dzięki którym pisanie testów jest dziecinnie proste. Kiedy piszę kod, który współdziała z interfejsami API, czuję się nieswojo, że moje testy w jakiś sposób mają rzeczywiste żądania sieciowe. Wprowadź zapobieganie błędnym żądaniom za pomocą klienta HTTP Laravela:

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.

Moim zdaniem najlepszym sposobem użycia preventStrayRequests() jest zdefiniowanie metody w klasach setUp() testowych, które mają wchodzić w interakcje z interfejsami API. Być może możesz również dodać go do klasy bazowej TestCase aplikacji:

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();
    }
}

Zrobienie tego zapewni, że każde wywołanie klienta HTTP wyzwalane w zestawie testowym ma fałszywe żądanie kopii zapasowej. Korzystanie z tej metody daje mi ogromny wzrost pewności, że pokryłem wszystkie moje żądania wychodzące w moich testach równoważnym fałszywym.

Rejestrowanie programów obsługi zdarzeń HTTP Klient

HTTP firmy Laravel zawiera cenne zdarzenia, których można użyć do szybkiego wykorzystania istotnych etapów cyklu życia żądania/odpowiedzi. W chwili pisania tego tekstu uruchamiane są trzy zdarzenia:

  • Illuminate\Http\Client\Events\RequestSending

Illuminate\Http\Client\Events\ResponseReceivedIlluminate\Http\Client\Events\ConnectionFailedZałóżmy, że chcesz wizualizować każdy adres URL, do którego aplikacja wysyła żądania. Możemy łatwo wykorzystać RequestSending zdarzenie i wylogować każde żądanie:Aby program obsługi zdarzeń działał, dodaj następujące elementy do EventServiceProvider klasy:Gdy wszystko zostanie podłączone, zobaczysz w dzienniku coś podobnego do każdego żądania podjętego za pomocą klienta 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"}

Dowiedz się więcej

Oficjalna dokumentacja Laravel HTTP zawiera wszystko, czego potrzebujesz, aby rozpocząć. Mam nadzieję, że ten samouczek dał ci inspirację i sztuczki, których możesz użyć w swoich aplikacjach Laravel

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

O

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...

O autorze CrazyBoy49z
WORK EXPERIENCE
Kontakt
Ukraine, Lutsk
+380979856297