使用 Laravel HTTP 客户端的 5 个技巧和窍门

最后更新于 作者:

5 Tips and Tricks for working with the Laravel HTTP Client image

作为 Web 开发人员,我们经常需要从 Laravel 应用程序中与 API 交互。在版本 7 中引入的 Laravel HTTP 客户端 提供了围绕 Guzzle HTTP 库的便捷且直观的包装器。在本文中,我们将探讨五个使用 Laravel HTTP 客户端的宝贵技巧,这些技巧可以使您的开发体验更加高效和愉快。

这些技巧包括使用 HTTP 宏、为容器服务配置 HTTP 客户端、可移植的基本 URL 配置、防止测试中的意外请求以及监听 HTTP 事件。通过掌握这些技巧,您可以简化 API 交互并创建更健壮、更易于维护的 Laravel 应用程序。

HTTP 宏

Laravel 的许多服务都具有“宏”功能,允许您为应用程序定义自定义方法。您可以将这些宏添加到服务提供者的 boot() 方法中,而不是从 Laravel 框架扩展核心类。

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 客户端

当从 Laravel 应用程序与 API 交互时,您可能希望为客户端设置各种可配置设置。例如,如果 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);
});
}

在单例服务定义中,我们已经连接了一些调用来配置客户端。结果是一个 PendingRequest 实例,我们可以像下面这样将其传递给我们的服务构造函数

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

该服务使用 withOptions() 方法直接配置 Guzzle 选项,但我们也可以使用 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);
});

或者,如果您希望将宏与服务结合使用,您可以使用在 AppServiceProvider 的 boot() 方法中定义的宏

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

可移植的基本 URL 配置

您可能已经看到默认的基本 URL 包含一个尾部的 /,因为它根据 RFC 3986 提供了我认为最可移植的选项。

以以下示例服务配置为例(注意默认的 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 在生产环境和预发布环境中有一个路径前缀 /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 的解析方式。

防止测试中的意外请求

Laravel 的 HTTP 客户端提供了出色的测试工具,使编写测试变得轻而易举。当我编写与 API 交互的代码时,我感到不安的是,我的测试以某种方式产生了实际的网络请求。使用 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 交互的测试类中定义一个 setUp() 方法。也许您还可以将其添加到应用程序的基本 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 事件的日志处理程序

Laravel 的 HTTP 客户端具有宝贵的事件,您可以使用这些事件快速进入请求/响应生命周期的重要阶段。在撰写本文时,会触发三个事件

  • Illuminate\Http\Client\Events\RequestSending
  • Illuminate\Http\Client\Events\ResponseReceived
  • Illuminate\Http\Client\Events\ConnectionFailed

假设您希望可视化应用程序发出的每个 URL 请求。我们可以轻松地利用 RequestSending 事件并记录每个请求

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

要使事件处理程序正常工作,请将以下内容添加到 EventServiceProvider 类中

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

一切准备就绪后,您将在日志中看到类似以下内容,用于使用 HTTP 客户端尝试的每个请求

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

了解更多

官方的 Laravel HTTP 文档 包含您入门所需的一切。我希望本教程能给您一些灵感和技巧,您可以在 Laravel 应用程序中使用这些技巧

Paul Redmond photo

Laravel 新闻的专栏作家。全栈 Web 开发人员和作家。

归档于
Cube

Laravel 新闻通讯

加入 40k+ 其他开发人员,绝不错过新的技巧、教程等。

Laravel Forge logo

Laravel Forge

轻松创建和管理您的服务器,并在几秒钟内部署您的 Laravel 应用程序。

Laravel Forge
Tinkerwell logo

Tinkerwell

Laravel 开发人员必备的代码运行器。使用 AI、自动完成和本地和生产环境的即时反馈进行调试。

Tinkerwell
No Compromises logo

绝不妥协

Joel 和 Aaron,来自“绝不妥协”播客的两位经验丰富的开发者,现在可以为您的 Laravel 项目提供服务。 ⬧ 固定价格 7500 美元/月。 ⬧ 无需冗长的销售流程。 ⬧ 无需合同。 ⬧ 100% 退款保证。

绝不妥协
Kirschbaum logo

Kirschbaum

提供创新和稳定性,以确保您的 Web 应用程序取得成功。

Kirschbaum
Shift logo

Shift

正在运行旧版本的 Laravel 吗?即时、自动化的 Laravel 升级和代码现代化,让您的应用程序保持新鲜。

Shift
Bacancy logo

Bacancy

只需每月 2500 美元,即可使用拥有 4-6 年经验的经验丰富的 Laravel 开发人员为您的项目注入活力。获得 160 小时的专用专业知识和 15 天的无风险试用期。立即预约电话!

Bacancy
Lucky Media logo

Lucky Media

立即获得幸运 - Laravel 开发的理想之选,拥有超过十年的经验!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel 电子商务

Laravel 的电子商务。一个开源软件包,它将现代无头电子商务功能的强大功能带到 Laravel。

Lunar: Laravel 电子商务
LaraJobs logo

LaraJobs

官方 Laravel 职位平台

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS 启动套件

SaaSykit 是一款 Laravel SaaS 启动工具包,包含运行现代 SaaS 所需的所有功能。包括支付、美观结账页面、管理面板、用户仪表盘、身份验证、即用型组件、统计数据、博客、文档等。

SaaSykit: Laravel SaaS 启动套件
Rector logo

Rector

您的 Laravel 无缝升级合作伙伴,帮助您降低成本,加速创新,助力企业取得成功。

Rector
MongoDB logo

MongoDB

通过 MongoDB 和 Laravel 的强大集成,增强您的 PHP 应用程序,使开发人员能够轻松高效地构建应用程序。支持事务性、搜索、分析和移动用例,同时使用熟悉的 Eloquent API。探索灵活的现代数据库 MongoDB 如何改变您的 Laravel 应用程序。

MongoDB
Maska is a Simple Zero-dependency Input Mask Library image

Maska 是一款简单无依赖的输入掩码库。

阅读文章
Add Swagger UI to Your Laravel Application image

在您的 Laravel 应用程序中添加 Swagger UI

阅读文章
Assert the Exact JSON Structure of a Response in Laravel 11.19 image

在 Laravel 11.19 中断言响应的精确 JSON 结构

阅读文章
Build SSH Apps with PHP and Laravel Prompts image

使用 PHP 和 Laravel Prompts 构建 SSH 应用程序

阅读文章
Building fast, fuzzy site search with Laravel and Typesense image

使用 Laravel 和 Typesense 构建快速、模糊的网站搜索

阅读文章
Add Comments to your Laravel Application with the Commenter Package image

使用 Commenter 包在您的 Laravel 应用程序中添加评论

阅读文章