分析總結(jié)5個(gè)Laravel HTTP Client小技巧

本篇文章給大家?guī)砹岁P(guān)于laravel的相關(guān)知識(shí),其中主要跟大家分享5個(gè)laravel http client的小技巧,感興趣的朋友下面一起來看一下吧,希望對(duì)大家有幫助。

作為web開發(fā)人員,我們經(jīng)常需要與來自Laravel應(yīng)用程序的api進(jìn)行交互。在Laravel HTTP客戶端版本7中提供了一個(gè)方便而直觀的Guzzle HTTP庫包裝器。在本文中,我們將探討使用Laravel HTTP Client的五個(gè)有價(jià)值的技巧,這些技巧可以使你的開發(fā)體驗(yàn)更加高效和愉快。

這些技巧包括使用HTTP宏、為容器服務(wù)配置HTTP客戶機(jī)、可移植的基本URL配置、防止測試中的雜發(fā)請(qǐng)求以及偵聽HTTP事件。通過掌握這些技巧,你可以簡化API交互并創(chuàng)建更健壯和可維護(hù)的Laravel應(yīng)用程序。

HTTP 宏

Laravel 的許多服務(wù)都有一個(gè)宏特性,允許你為應(yīng)用程序定義自定義方法。你可以將這些宏添加到服務(wù)提供者的boot()方法中,而不是從 Laravel 框架擴(kuò)展核心類。

HTTP 文檔中展示了一個(gè)宏的示例,你可以使用它來定義常見的設(shè)置:

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

宏可以定義任何你想在應(yīng)用程序中定義和重復(fù)使用的便捷方法。文檔中的宏示例涉及到了另一個(gè)配置 HTTP 客戶端用于在其他服務(wù)中使用的提示。

在下一節(jié)中,我們將重溫將宏與傳遞客戶端到其他容器服務(wù)相結(jié)合的方法。

配置容器服務(wù)的 HTTP 客戶端

在 Laravel 應(yīng)用程序中與 API 交互時(shí),你可能希望為客戶端配置各種可配置的設(shè)置。例如,如果 API 具有多個(gè)環(huán)境,則需要配置基本 URL、令牌、超時(shí)設(shè)置等。

我們可以利用宏來定義客戶端,將客戶端表示為自己的服務(wù),然后將其注入到其他服務(wù)中,或者兩者都有。

首先,讓我們看看如何在服務(wù)提供者的 register() 方法中定義客戶端設(shè)置:

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ù)定義中,我們鏈?zhǔn)秸{(diào)用了一些調(diào)用以配置客戶端。結(jié)果是一個(gè) PendingRequest 實(shí)例,我們可以將其傳遞給我們的服務(wù)構(gòu)造函數(shù),如下所示:

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

該服務(wù)使用 withOptions() 方法直接配置 Guzzle 選項(xiàng),但我們也可以使用 HTTP 客戶端提供的一些便捷方法:

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

或者,如果你想將宏與服務(wù)相結(jié)合,可以在你的 AppServiceProvider 的 boot() 方法中使用你定義的宏:

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

可移植的基礎(chǔ) URL 配置

你可能已經(jīng)看到默認(rèn)的基礎(chǔ) URL 包含一個(gè)尾隨的 /,根據(jù) 示例,這提供了最大的可移植性。

以下面的服務(wù)配置為例 (注意默認(rèn)的 base_url):

return [     '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 在生產(chǎn)和測試環(huán)境中有一個(gè)路徑前綴 /v1/ ,也許它只是 https://stg-api.example.com/; 使用尾部斜線可以使 URL 按預(yù)期工作,而不會(huì)更改代碼。在配置尾部 / 的同時(shí),請(qǐng)注意,我的代碼中的所有 API 調(diào)用都使用相對(duì)路徑:

$this->client     ->withUrlParameters(['uid' => $uid])     // 例子:     // 測試環(huán)境 - https://stg-api.example.com/widget/123     // 生產(chǎn)環(huán)境 - https://api.example.com/v1/widget/123     ->get('widget/{uid}');

請(qǐng)參閱 Guzzle 的示例文檔,了解不同的 base_uri 風(fēng)格是如何影響 URI 的解析的。

防止測試中的雜散請(qǐng)求

Laravel 的 HTTP 客戶端提供了優(yōu)秀的測試工具,使編寫測試變得輕而易舉。當(dāng)我寫與 API 交互的代碼時(shí),我感到不安的是我的測試在某種程度上有實(shí)際的網(wǎng)絡(luò)請(qǐng)求發(fā)生。進(jìn)入示例與 Laravel 的 HTTP 客戶端:

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() 的最好方法是在你期望與 API 交互的測試類中定義一個(gè) setUp() 方法。也許你也可以把它添加到你的應(yīng)用程序的基礎(chǔ) TestCase 類中。

namespace Tests;  use IlluminateFoundationTestingTestCase as BaseTestCase; use IlluminateSupportFacadesHttp;  abstract class TestCase extends BaseTestCase {     use CreatesApplication;      public function setUp(): void     {         parent::setUp();          Http::preventStrayRequests();     } }

這樣做將確保你的測試套件中觸發(fā)的每個(gè) HTTP 客戶端調(diào)用都有一個(gè)假的請(qǐng)求支持。使用這種方法給了我很大的信心,我已經(jīng)在我的測試中用一個(gè)等價(jià)的假請(qǐng)求覆蓋了我所有的出站請(qǐng)求。

HTTP 事件的日志處理程序

Laravel 的 HTTP 客戶端有很多有價(jià)值的事件,你可以用它們來快速挖掘請(qǐng)求/響應(yīng)生命周期的重要階段。在寫這篇文章的時(shí)候,有三個(gè)事件被觸發(fā):

  • IlluminateHttpClientEventsRequestSending
  • IlluminateHttpClientEventsResponseReceived
  • IlluminateHttpClientEventsConnectionFailed

比方說,你想把你的應(yīng)用程序發(fā)出請(qǐng)求的每個(gè) URL 都可視化。我們可以很容易地接入 RequestSending 事件,并記錄出每個(gè)請(qǐng)求。

namespoace App/Listeners;  use IlluminateContractsQueueShouldQueue; use IlluminateQueueInteractsWithQueue; use IlluminateSupportFacadesLog;  class LogRequestSending {     public function handle(object $event): void     {         Log::debug('HTTP請(qǐng)求正在發(fā)送。', ['url' => $event->request->url()             'url' => $event->request->url(),         ]);     } }

為了使事件處理程序工作,在 EventServiceProvider 類中添加以下內(nèi)容。

use AppListenersLogRequestSending; use IlluminateHttpClientEventsRequestSending; // ... protected $listen = [     Registered::class => [         SendEmailVerificationNotification::class,     ],     RequestSending::class => [         LogRequestSending::class,     ], ];

一旦它被連接起來,你就會(huì)在你的日志中看到類似于 HTTP 客戶端嘗試的每個(gè)請(qǐng)求的內(nèi)容。

[2023-03-17 04:06:03] local.DEBUG: HTTP請(qǐng)求正在被發(fā)送。{"url": "https://api.example.com/v1/widget/123"}

了解更多

官方的示例有你需要的一切,可以開始了。我希望這個(gè)教程能給你一些靈感和技巧,你可以在你的 Laravel 應(yīng)用程序中使用。

原文地址:示例

譯文地址:示例

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊11 分享