Bisakah saya membuat cURL gagal dengan exitCode berbeda dari 0 jika kode status HTTP tidak 200?

239

Saya selalu berasumsi bahwa ketika curl mendapat respons HTTP 500 itu mengembalikan kode keluar yang berarti kegagalan (! = 0), tetapi itu tampaknya tidak terjadi.

Apakah ada cara saya dapat membuat cURL gagal dengan exitCode berbeda dari 0 jika kode status HTTP tidak 200? Saya tahu saya bisa menggunakan -w "%{http_code}"tetapi yang meletakkannya di STDOUT, bukan sebagai kode keluar (selain itu, saya juga tertarik untuk menangkap output, yang saya tidak ingin mengarahkan ulang ke file, tetapi ke layar).

knocte
sumber

Jawaban:

264

curl --fail melakukan bagian dari apa yang Anda inginkan:

dari man curl:

-f, --fail

(HTTP) Gagal diam-diam (tidak ada output sama sekali) pada kesalahan server. Hal ini sebagian besar dilakukan untuk mengaktifkan skrip dll untuk lebih baik dalam menghadapi upaya yang gagal. Dalam kasus normal ketika server HTTP gagal mengirimkan dokumen, ia mengembalikan dokumen HTML yang menyatakan demikian (yang sering juga menjelaskan alasan dan lebih banyak lagi). Bendera ini akan mencegah curl menghasilkan dan mengembalikan kesalahan 22.

Metode ini tidak aman-gagal dan ada kesempatan di mana kode respons yang tidak berhasil akan lolos, terutama ketika otentikasi terlibat (kode respons 401 dan 407).

Tapi itu memblokir output ke layar.

rampion
sumber
2
Jadi bagian mana yang berfungsi dan tidak dilakukan?
rogerdpack
5
@rogerdpack tl; dr tidak mengembalikan nol ketika mendeteksi respons buruk, tetapi OP tidak akan menangkap respons
rampion
3
Ini tidak menangkap HTTP 301 Bergerak Secara Permanen. curl masih memberikan kode keluar 0.
wisbucky
4
@wisbucky 301 bukan kesalahan, ini kode status pengalihan. Kesalahan adalah kode status 4xx dan 5xx.
M. Justin
1
@wisbucky untuk keluar dari nol pada kode kesalahan HTTP dan menangani pengalihan HTTP dengan benar gunakan curl -f -Ldan lihat pertanyaan ini untuk perincian tentang apa yang -Ldilakukan.
Noah Sussman
81

Jika Anda hanya ingin menampilkan konten halaman yang digulung, Anda dapat melakukan ini:

STATUSCODE=$(curl --silent --output /dev/stderr --write-out "%{http_code}" URL)

if test $STATUSCODE -ne 200; then
    # error handling
fi

Ini menulis konten halaman ke STDERR sambil menulis kode status HTTP ke STDOUT, sehingga dapat ditugaskan ke variabel STATUSCODE .

Dennis
sumber
3
Bagaimana jika saya ingin menampilkan respons pada kegagalan (bukan 200) , tetapi mengembalikan 0kode non status dari skrip?
Justin
2
@Justin: Bagaimana if [ "$statuscode" -ne 200 ]; then exit "$statuscode"; fi?
ghoti
4
@ ghoti: Hanya kode keluar 8-bit yang tidak ditandatangani yang didukung, sehingga bisa sedikit membingungkan.
Dennis
3
Ah, benar - dan kode akan membungkus pada 8 bit, jadi error 404 menjadi nilai keluar 148, 500 menjadi 244. Memang membingungkan! :-)
ghoti
7
Sebagai sedikit variasi, ini menangkap kode dalam sebuah variabel sambil mengarahkan respons ke stdout, bukan stderr: { code=$(curl ... as above ...); } 2>&1Triknya adalah { ... } 2>&1memungkinkan pengalihan, sementara tidak menghasilkan shell yang berbeda seperti yang ( ... )seharusnya.
Tobia
31

Saya dapat melakukannya menggunakan kombinasi flag:

curl --silent --show-error --fail URL

--silent menyembunyikan progres dan kesalahan
--show-error menunjukkan pesan kesalahan disembunyikan oleh --silent
--fail mengembalikan kode keluar> 0 ketika permintaan gagal

Ricardo Souza
sumber
5
Ini tidak menunjukkan balasan server. Saya bukan OP tetapi saya menduga dia ingin melihat pesan kesalahan dari server yang dikembalikan dalam tubuh. Selain itu --silent --show-error --failkarya sama dengan adil -f/--fail.
buang
1
Sebenarnya, --failmengembalikan kode keluar 22, seperti yang didokumentasikan .
Pertanyaan Quolonel
2
@wisbucky 301 bukan kesalahan, ini kode status pengalihan. Kesalahan adalah kode status 4xx dan 5xx.
M. Justin
4
Agar adil kepada @wisbucky, pertanyaan awal menyatakan "[...] jika kode status HTTP tidak 200" . Tidak disebutkan "kesalahan" di manapun sebelumnya.
ken
2
@ M.Justin Menurut curl man-page: Metode ini tidak gagal-aman dan ada saat-saat di mana kode respons yang tidak berhasil akan lolos, terutama ketika otentikasi terlibat (kode respons 401 dan 407).
youfu
0

Ya ada cara untuk melakukannya tetapi jauh dari jelas karena melibatkan 3 opsi ikal:

curl -s --fail --show-error https://httpbin.org/status/200 > /dev/null
curl -s --fail --show-error https://httpbin.org/status/401 > /dev/null
curl -s --fail --show-error https://httpbin.org/status/404 > /dev/null
curl -s --fail --show-error https://bleah-some-wrong-host > /dev/null

Ini memastikan bahwa keberhasilan (0) hanya terjadi ketika curl end-us dengan 2xxkode pengembalian akhir dan yang stdoutmendapatkan tubuh dan bahwa setiap kesalahan akan ditampilkan ke stderr.

Harap dicatat bahwa dokumentasi curl mungkin sedikit membingungkan Anda karena menyebutkan bahwa --fail bisa berhasil untuk 401 kode. Berdasarkan tes yang tidak benar, setidaknya tidak ketika digunakan dengan --show-error pada saat yang sama.

Sejauh ini saya tidak dapat menemukan kasus di mana curl akan mengembalikan kesuksesan ketika bukan http-succes dengan opsi ini.

Sorin
sumber
1
apakah ini jawaban yang pada dasarnya sama dengan Ricardo Souza?
knocte