Saya ingin menangani kesalahan dari Guzzle ketika server mengembalikan kode status 4xx dan 5xx. Saya membuat permintaan seperti ini:
$client = $this->getGuzzleClient();
$request = $client->post($url, $headers, $value);
try {
$response = $request->send();
return $response->getBody();
} catch (\Exception $e) {
// How can I get the response body?
}
$e->getMessage
mengembalikan info kode tetapi bukan isi respons HTTP. Bagaimana saya bisa mendapatkan respons tubuh?
Jawaban:
Guzzle 3.x
Sesuai dokumen , Anda dapat menangkap jenis pengecualian yang sesuai (
ClientErrorResponseException
untuk kesalahan 4xx) dan memanggilgetResponse()
metodenya untuk mendapatkan objek respons, lalu memanggilnyagetBody()
:Meneruskan
true
kegetBody
fungsi menunjukkan bahwa Anda ingin mendapatkan isi respons sebagai string. Jika tidak, Anda akan mendapatkannya sebagai contoh kelasGuzzle\Http\EntityBody
.sumber
Guzzle 6.x
Menurut dokumen , jenis pengecualian yang mungkin perlu Anda tangkap adalah:
GuzzleHttp\Exception\ClientException
untuk kesalahan 400 levelGuzzleHttp\Exception\ServerException
untuk kesalahan 500 levelGuzzleHttp\Exception\BadResponseException
untuk keduanya (itu superclass mereka)Kode untuk menangani kesalahan seperti itu sekarang terlihat seperti ini:
sumber
$response->getBody()->getContents()
akan mengembalikan string kosong. Saya kemudian menemukan ini di dokumen :\GuzzleHttp\Psr7\str($e->getResponse())
Mentransmisikan respons sebagai Psr7 String memberi saya pesan kesalahan yang diformat dengan baik dan lengkap.Psr7\str()
akan memiliki hasil yang berbeda kepada->getContents()
. Apakah Anda memiliki contoh minimal yang menunjukkan ini, yang mungkin membuat saya memahami ini dan mungkin memperbarui jawaban ini?'http_errors' => false
opsi dapat diteruskan dalam permintaan Guzzle yang menonaktifkan pengecualian lemparan. Anda kemudian bisa mendapatkan tubuh$response->getBody()
tanpa peduli apa kode statusnya, dan Anda bisa menguji kode status jika perlu dengan$response->getStatusCode()
.$response->getBody()->getContents()
memberi saya string kosong dalam satu kasus, saya tidak mengerti mengapa. Tetapi menggunakan\GuzzleHttp\Psr7\str()
mengembalikan semua respons HTTP sebagai string, dan saya hanya akan tubuh HTTP. Seperti yang dikatakan dalam dokumentasi , bodi dapat digunakan dengan mentransmisikannya ke string.$stringBody = (string) $clientException->getResponse()->getBody();
\GuzzleHttp\Exception\RequestException
yang mengembalikan400
kode status. coba {$ request-> api ('POST', 'endpoint.json'); } menangkap (RequestException $ e) {print_r ($ e-> getResponse () -> getBody () -> getContents ()); }Meskipun jawaban di atas bagus, mereka tidak akan menangkap kesalahan jaringan. Seperti yang disebutkan Mark, BadResponseException hanyalah kelas super untuk ClientException dan ServerException. Tapi RequestException juga merupakan kelas super BadResponseException. RequestException tidak hanya akan terjadi 400 dan 500 kesalahan tetapi juga kesalahan jaringan dan pengalihan tak terbatas. Jadi katakanlah Anda meminta halaman di bawah ini tetapi jaringan Anda sedang bermain dan tangkapan Anda hanya mengharapkan BadResponseException. Nah aplikasi Anda akan membuat kesalahan.
Lebih baik dalam kasus ini mengharapkan RequestException dan memeriksa respons.
sumber
JsonResponse
dengan kelas dari Guzzle?JsonResponse
berasal dari SymfonyMulai 2019, inilah yang saya uraikan dari jawaban di atas dan dokumen Guzzle untuk menangani pengecualian, mendapatkan isi respons, kode status, pesan, dan item respons terkadang berharga lainnya.
Voila. Anda mendapatkan informasi respons dalam item yang dipisahkan dengan mudah.
Catatan Samping:
Dengan
catch
klausa kita menangkap rantai warisan kelas pengecualian akar PHP\Exception
sebagai pengecualian khusus Guzzle memperluasnya.Pendekatan ini mungkin berguna untuk kasus penggunaan di mana Guzzle digunakan secara tersembunyi seperti di Laravel atau AWS API PHP SDK sehingga Anda tidak dapat menangkap pengecualian Guzzle asli.
Dalam kasus ini, kelas pengecualian mungkin bukan yang disebutkan dalam dokumen Guzzle (misalnya
GuzzleHttp\Exception\RequestException
sebagai pengecualian root untuk Guzzle).Jadi, Anda harus menangkapnya,
\Exception
tetapi perlu diingat bahwa ini masih merupakan instance kelas pengecualian Guzzle.Meskipun digunakan dengan hati-hati. Pembungkus tersebut mungkin membuat
$e->getResponse()
metode asli objek Guzzle tidak tersedia. Dalam kasus ini, Anda harus melihat kode sumber pengecualian aktual pembungkus dan mencari tahu bagaimana mendapatkan status, pesan, dll. Daripada menggunakan$response
metode Guzzle .Jika Anda memanggil Guzzle sendiri secara langsung, Anda dapat menangkap
GuzzleHttp\Exception\RequestException
atau yang lain yang disebutkan dalam dokumen pengecualian mereka sehubungan dengan kondisi kasus penggunaan Anda.sumber
$response
objek Anda saat menangani pengecualian kecuali Anda telah memeriksanya$e->hasResponse()
, jika tidak$response
mungkinnull
dan panggilan metode apa pun akan menyebabkan kesalahan fatal.$e->hasResponse
hasilnya, sebuah metode yang, tentu saja, tidak ada untuk pengecualian non-Guzzle. Jadi jika Anda memunculkan pengecualian non-Guzzle daritheMethodMayThrowException()
, kode ini akan menangkapnya, mencoba memanggil metode yang tidak ada, dan macet karena metode yang tidak ada, secara efektif menyembunyikan penyebab sebenarnya dari kesalahan tersebut. Lebih disukai menangkapGuzzleHttp\Exception\RequestException
daripadaException
menghindari ini.jika put
'http_errors' => false
dalam pilihan permintaan membuang waktu, maka akan berhenti pengecualian melemparkan sementara mendapatkan 4xx atau 5xx error, seperti ini:$client->get(url, ['http_errors' => false])
. lalu anda parsing responnya, tidak masalah ok atau error, itu akan di respon untuk info lebih lanjutsumber