خیلی وقتا فعالیت برنامه ما وابسته به یک برنامه دیگه هست . ما توی قسمت Frontend برای ارتباط با یک سرور دیگه از ایجکس استفاده میکنیم . اما توی قسمت Backend اگه به اطلاعاتی از یک سرور دیگه لازم داشته باشیم ، چطوری میتونیم درخواست ارسال کنیم و پاسخ بگیریم ؟ شاید قبلاً از cURL یا Guzzle استفاده میکردیم . اما همیشه راه راحتتری وجود داره ! اگه از فریمورک لاراول استفاده میکنیم ، میتونیم این کار رو با یک ابزار ساده ، سریع و در حین حال قدرتمند به اسم HTTP Client انجام بدیم .
HTTP Client چیه ؟
HTTP Client لاراول ابزاری هست که برای ارسال درخواستهای HTTP و تعامل با سرویسهای تحت وب استفاده میشه . HTTP Client پشت پرده از پکیج گازِل (Guzzle) استفاده میکنه و برای این معرفی شده تا کار با اون رو سادهتر و سریعتر کنه . به قول معروف ، یک Wrapper هست برای گازِل .
با HTTP Client ، بدون پیچیدگیهایی که گازل داره ، میتونیم درخواستهای HTTP به یک سرور دیگه بفرستیم :
Http::get('http://test.com');
توی ادامه این ابزار رو بررسی میکنیم و با نکات کاربردی اون آشنا میشیم
چون این ابزار از Guzzle استفاده میکنه ، قبل از شروع باید از نصب اون مطمئن بشیم . توی یک برنامه لاراولی، Guzzle بطور پیشفرض اضافه شده . هر چند میتونیم اون رو با دستور کامپوزر زیر نصب کنیم :
composer require guzzlehttp/guzzle
یک درخواست بسازیم
ساختن یک درخواست با HTTP Client به سادگی کد زیر هست . برای ساختن یک درخواست GET ، از متد get کلاس Http استفاده میکنیم :
use Illuminate\Support\Facades\Http;
$response = Http::get('http://test.com');
برای ارسال درخواستهای POST و ... متدهایی با همین اسم وجود داره :
این متد اهمیت زیادی داره چون بیشتر متدهای کلاس Response از این متد استفاده میکنن که با اونها آشنا میشیم .
آیا درخواست موفقیت آمیز بود ؟
با متد successful() میتونیم بررسی کنیم که آیا درخواست ما موفقیت آمیز بود یا خیر :
$response = Http::get('http://test.com');
if ($response->successful()) {
// do something
}
ببینیم متد successful() پشت پرده دقیقاً چه کاری انجام میده :
public function successful()
{
return $this->status() >= 200 && $this->status() < 300;
}
همونطور که میبینیم این متد بررسی میکنه که آیا status() بین ۲۰۰ و ۳۰۰ هست یا خیر .
اگه بخوایم بررسی کنیم که آیا کد نتیجه درخواست دقیقاً برابر با ۲۰۰ هست ، از متد ok() استفاده میکنیم :
$response = Http::get('http://test.com');
if ($response->ok()) {
// The HTTP status code is 200
}
درخواست با خطا مواجه شد ؟
برای اینکه بررسی کنیم آیا درخواست ما با خطا مواجه شده ، از متد failed() استفاده میکنیم :
$response = Http::get('http://test.com/failing-url');
if ($response->failed()) {
// Request failed
}
این متد جزییات زیادی رو در اختیار ما نمیگذاره . خوبه با کاری که این متد انجام میده هم آشنا بشیم . متد failed() خودش از دو تا متد دیگه استفاده میکنه :
public function failed()
{
return $this->serverError() || $this->clientError();
}
البته از این متدها میتونیم بصورت جدا هم استفاده کنیم .
همونطور که میدونیم اگه خطا از سمت سرور باشه ، کد HTTP از عدد ۵۰۰ شروع میشه . متد serverError() هم دقیقاً همین رو بررسی میکنه :
public function serverError()
{
return $this->status() >= 500;
}
و همچنین اگه خطا به درخواست کاربر ارتباط داشته باشه ، کد HTTP از ۴۰۰ تا ۵۰۰ خواهد بود که متد clientError() همین رو بررسی میکنه :
public function clientError()
{
return $this->status() >= 400 && $this->status() < 500;
}
اطلاعات پاس بدیم
از آرگومان دوم میتونیم برای پاس دادن اطلاعات اضافی استفاده کنیم :
در حالت پیشفرض ، همه اطلاعات با هدر Content-Type با مقدار application/json فرستاده میشه . اما تو درخواست POST اگه بخوایم اطلاعات رو مثل یک فرم بفرستیم ، از متد asForm() بصورت زیر استفاده میکنیم :
با این کار ، مقدار هدر Content-Type به application/x-www-form-urlencoded تغییر پیدا میکنه . اما با این هدر نمیتونیم فایل ارسال کنیم . برای ارسال و ضمیمه کردن فایل به درخواست ، از متد attach() استفاده میکنیم :
توی مثال بالا ، آرگومان اول متد attach() اسم پارامتری هست که پاس میدیم . آرگومان دوم محتویات فایل هست . آرگومان سوم اختیاری هست و مقدار اون در نظر گرفته میشه برای اسم فایل .
برای ضمیمه کردن چند فایل باید چند بار از متد attach() استفاده کنیم . اما راه راحتتر اینه که این کار رو با یک متد انجام بدیم .
پس اگه چند تا فایل داریم میتونیم از متد attachMany() استفاده کنیم :
و اگه نیاز به تنظیم کردن هدر Authorization داریم ، میتونیم بطور مستقیم از متد withToken() استفاده کنیم :
$response = Http::withToken('token')->post(...);
این متد دو تا پارامتر میگیره . پارامتر اول توکن و پارامتر دوم نوع توکن هست که بطور پیشفرض Bearer در نظر گرفته میشه .
چقدر صبر کنیم برای پاسخ ؟
با استفاده از متد timeout() میتونیم مشخص کنیم حداکثر چند ثانیه منتظر اومدن پاسخ باشیم :
$response = Http::timeout(3)->get(...);
اگه توی بازه زمانی مشخص شده پاسخی نیومد ، یک Exception از نوع Illuminate\Http\Client\ConnectionException خواهیم داشت .
دوباره تلاش کن
اگه درخواست با خطا مواجه شد ، این امکان وجود داره که بطور خودکار درخواست رو دوباره بفرستیم . برای این کار از متد retry() استفاده میکنیم . این متد ۲ آرگومان قبول میکنه . توی آرگومان اول میگیم چند بار تلاش کن و توی آرگومان دوم مشخص میکنیم که درخواست بعدی با چقدر تاخیر شروع بشه . این مقدار رو به میلیثانیه مشخص میکنیم :
$response = Http::retry(3, 100)->get(...);
اگه همه درخواستها با خطا مواجه بشه، یک Exception از نوع Illuminate\Http\Client\RequestException خواهیم داشت .
مدیریت خطاها
توی پکیج گازل ، خطاهای 4xx و 5xx باعث به وجود اومدن Exception میشد . اما توی HTTP Client این اتفاق نمیافته و همونطور که بررسی کردیم ، برای مدیریت این خطاها از متدهای زیر استفاده میکنیم :
خیلی وقتها میخوایم برنامه رو تست کنیم و لازم نیست درخواست واقعی زده بشه . مثلاً میخوایم مراحل بعد از درخواست رو بنویسیم و توسعه بدیم . اگه از متد fake() بصورت زیر استفاده کنیم ، درخواست واقعی اتفاق نمیافته و همچنین کد HTTP برای هر درخواست ۲۰۰ خواهد بود :
Http::fake();
$response = Http::post(...);
اگه میخوایم کد HTTP رو تغییر بدیم میتونیم از کد زیر استفاده کنیم :
Http::fake(function($request) {
return Http::response(['message' => '...'], 400);
});
$response = Http::get('...');
if ($response->failed()) {
// do something
}
اگه میخوایم فقط یک سری آدرسهای خاص رو fake() کنیم ، اونها رو بصورت زیر تعریف میکنیم :