HTTP client
Setiap panggilan ke layanan luar adalah titik kegagalan yang bisa menyeret aplikasimu ikut mati. Klien HTTP Laravel membuat pengaman untuk itu jadi satu baris, bukan satu proyek.
Intisari
- Selalu setel timeout. Tanpa itu, layanan luar yang menggantung akan menahan worker-mu.
retry()dengan jeda menaik untuk kegagalan sementara.- Respons tidak melempar exception secara default โ panggil
throw()atau periksafailed(). Http::fake()membuat tes berjalan tanpa jaringan sama sekali.- Panggilan luar di dalam siklus permintaan sebaiknya dipindahkan ke antrean.
Bentuk yang layak dipakai di produksi
use Illuminate\Support\Facades\Http;
$respons = Http::withToken(config('services.mitra.token'))
->timeout(5) // batas total
->connectTimeout(2) // batas membangun koneksi
->retry(3, 200, throw: false)
->acceptJson()
->get('https://api.mitra.test/artikel', ['halaman' => 1]);
if ($respons->failed()) {
Log::warning('mitra gagal', ['status' => $respons->status()]);
return null;
}
$data = $respons->json('data');
Timeout adalah setelan terpenting di halaman ini. Tanpa itu, satu layanan luar yang lambat akan menahan proses PHP-mu tanpa batas. Sepuluh permintaan seperti itu berarti sepuluh worker terpakai; seratus, dan seluruh aplikasi berhenti merespons โ padahal kodemu sendiri baik-baik saja. Angka yang sehat: total lebih pendek daripada timeout permintaan HTTP-mu sendiri, dan jauh lebih pendek daripada kesabaran pengguna.
Retry yang tidak memperburuk keadaan
Http::retry(
times: 3,
sleepMilliseconds: fn (int $percobaan) => $percobaan * 200, // 200, 400, 600
when: fn (Throwable $e, $req) => $e instanceof ConnectionException,
)->post($url, $data);
| Kondisi | Boleh diulang? |
|---|---|
| Timeout koneksi, 502, 503, 504 | Ya โ kemungkinan besar sementara |
| 429 Too Many Requests | Ya, tapi tunggu sesuai Retry-After |
| 400, 422 (permintaanmu salah) | Tidak โ mengulang menghasilkan hasil yang sama |
| 401, 403 | Tidak โ masalah kredensial |
POST yang tidak idempoten | Hati-hati โ bisa jadi tagihan dobel |
Mengulang POST itu berbahaya. Kalau permintaan pertama sebenarnya sampai dan diproses,
tapi responsnya yang hilang, percobaan kedua akan membuat pesanan atau tagihan kedua. Untuk operasi yang
mengubah keadaan, kirim kunci idempotensi yang dikenali penyedia โ atau jangan ulangi sama sekali.
Klien yang punya nama
// AppServiceProvider::boot()
Http::macro('mitra', fn () => Http::baseUrl(config('services.mitra.url'))
->withToken(config('services.mitra.token'))
->timeout(5)
->retry(3, 200)
->acceptJson());
Http::mitra()->get('/artikel');
Http::mitra()->post('/artikel', $data);
Manfaatnya: setelan timeout dan retry ditulis sekali. Tidak ada lagi satu pemanggilan yang lupa timeout karena ditulis buru-buru pada hari Jumat sore.
Menguji tanpa jaringan
Http::fake([
'api.mitra.test/artikel*' => Http::response(['data' => [['id' => 1]]], 200),
'api.lain.test/*' => Http::response(null, 500),
'*' => Http::response('tidak terduga', 404),
]);
$this->get('/impor');
Http::assertSent(fn ($req) =>
$req->hasHeader('Authorization') && $req->url() === 'https://api.mitra.test/artikel?halaman=1');
// Urutan respons: gagal dulu, lalu berhasil โ untuk menguji jalur retry
Http::fakeSequence()
->push(null, 500)
->push(['data' => []], 200);
Tambahkan Http::preventStrayRequests() di TestCase-mu. Dengan itu, setiap
panggilan HTTP yang tidak di-fake akan menggagalkan tes alih-alih diam-diam menghubungi internet.
Tanpa itu, suite tes bisa mengirim permintaan sungguhan ke penyedia โ lambat, tidak stabil, dan sesekali
benar-benar memicu efek samping di dunia nyata.
Panggilan bersamaan
$hasil = Http::pool(fn (Pool $pool) => [
$pool->as('cuaca')->get('https://api.cuaca.test/hari-ini'),
$pool->as('kurs')->get('https://api.kurs.test/idr'),
$pool->as('bursa')->get('https://api.bursa.test/ihsg'),
]);
$cuaca = $hasil['cuaca']->json();
Tiga panggilan berurutan yang masing-masing 300 ms memakan 900 ms; dijalankan bersamaan, sekitar 300 ms. Untuk halaman yang menggabungkan beberapa sumber, ini perbedaan yang langsung terasa.
Aturan yang menyelamatkan produksi
- Selalu timeout. Tidak ada pengecualian.
- Panggilan yang tidak dibutuhkan untuk merender halaman pindahkan ke antrean.
- Cache respons yang jarang berubah โ sekaligus melindungimu dari rate limit penyedia.
- Jangan pernah mencatat isi respons mentah tanpa disaring; di dalamnya sering ada token dan data pribadi.
- Sediakan perilaku cadangan saat penyedia mati: nilai terakhir yang di-cache, atau bagian halaman yang dihilangkan โ bukan halaman 500.
Latihan: buat macro Http::mitra() dengan timeout 3 detik dan retry 2 kali, panggil URL
yang sengaja lambat (https://httpbin.org/delay/10), dan pastikan aplikasimu menyerah setelah
3 detik. Lalu tulis tesnya dengan Http::fakeSequence() yang gagal sekali lalu berhasil.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.