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\ResponseReceived
Illuminate\Http\Client\Events\ConnectionFailed
Załóż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