cfhttp: panggilan API luaran dengan SSL, timeout dan multipart
Panduan cfhttp Lucee: panggil API luaran dengan GET dan POST, hurai JSON guna deserializeJSON, pasang sijil SSL ke truststore, kawal timeout dan redirect.

Kandungan
- cfhttp: panggilan API luaran dengan SSL, timeout dan multipart
- Apa itu cfhttp dan Bila Menggunakannya
- GET Asas dan Menghurai JSON
- POST dengan Badan JSON
- Menghantar Medan Borang dan Multipart
- Timeout, Redirect dan Pengendalian Ralat
- SSL dan Sijil Pelayan
- Muat Turun Fail dan Cache Respons
- Pengesahan Asas dan Sijil Klien
- Soalan Lazim (FAQ)
- Sumber
cfhttp: panggilan API luaran dengan SSL, timeout dan multipart
cfhttp ialah tag teras Lucee untuk membuat permintaan HTTP ke pelayan luaran. Ia menyokong semua kaedah HTTP, menghantar badan JSON atau medan borang, dan memulangkan respons dalam struct yang anda namakan melalui atribut result. Artikel ini menunjukkan GET dan POST asas, cara menghurai JSON dengan deserializeJSON, menghantar medan borang multipart, menetapkan timeout dan redirect, serta mengatasi ralat sijil SSL. Semua fakta di sini disahkan berjalan pada Lucee 7.1.
Apa itu cfhttp dan Bila Menggunakannya
cfhttp adalah cara standard CFML untuk bercakap dengan dunia luar: memanggil API kerajaan, gerbang pembayaran, atau perkhidmatan dalaman anda sendiri. Ia sama peranannya dengan curl atau fetch dalam bahasa lain, tetapi bersepadu terus dengan enjin CFML. Apabila anda membina REST API dengan Lucee, klien kepada API itu selalunya ditulis dengan cfhttp juga.
Atribut wajib hanya satu: url, yang mesti lengkap dengan protokol dan hostname, contohnya https://api.contoh.com/data. Secara lalai method ialah GET, dan hasil panggilan disimpan dalam struct bernama cfhttp melainkan anda menetapkan atribut result. Setiap kali anda memanggil API yang memerlukan kunci atau token, simpan nilai itu dalam pemboleh ubah persekitaran dan baca melalui skop application, seperti yang diterangkan dalam panduan rahsia dan pemboleh ubah persekitaran, dan jangan sekali-kali tulis kunci terus dalam kod.
GET Asas dan Menghurai JSON
Bentuk paling ringkas ialah GET dengan parameter query. Parameter dihantar melalui tag anak cfhttpparam dengan type="url", dan respons dibaca daripada struct result:
<cfhttp url="https://api.contoh.com/data" method="get" result="resp">
<cfhttpparam type="url" name="q" value="Lucee">
</cfhttp>
<cfscript>
if (resp.ERROR eq "" AND left(resp.statusCode, 3) == "200") {
data = deserializeJSON(resp.fileContent);
writeDump(data);
} else {
writeOutput("Ralat: " & resp.statusCode);
}
</cfscript>
Balasan JSON disimpan dalam resp.fileContent sebagai rentetan, jadi anda mesti menukarnya dengan deserializeJSON sebelum boleh membaca medan seperti data.location atau data.max_temp. Status HTTP dibaca daripada resp.statusCode, dan kekunci ERROR dalam struct memberitahu sama ada panggilan itu gagal di peringkat rangkaian. Struct hasil membawa lebih daripada badan: selain fileContent, anda mendapat responseheader yang memegang pengepala yang dipulangkan pelayan, statuscode, dan kekunci ERROR. Untuk mengikuti redirect secara manual, pengepala Location dibaca melalui resp.responseHeader.LOCATION.
POST dengan Badan JSON
Untuk API moden, anda menghantar JSON melalui POST. Cara paling selamat ialah membina struct, menukarnya dengan serializeJSON, kemudian menghantarnya sebagai body dengan pengepala Content-Type yang betul:
<cfscript>
payload = { nama = "Ali Abu", jumlah = 150 };
badan = serializeJSON(payload);
cfhttp(url = "https://api.contoh.com/bayaran", method = "post", result = "resp") {
cfhttpparam(type = "header", name = "Content-Type", value = "application/json");
cfhttpparam(type = "body", value = badan);
}
jawapan = deserializeJSON(resp.fileContent);
writeDump(jawapan);
</cfscript>
Tag cfhttpparam jenis body menghantar kandungan mentah tanpa sebarang pengekodan, jadi ia sesuai untuk JSON, XML atau apa-apa muatan mentah. Apabila anda kemudian mahu menyimpan data daripada jawapan ke pangkalan data, gunakan query berparameter seperti yang dijelaskan dalam panduan cfquery dan cfqueryparam.
Menghantar Medan Borang dan Multipart
Sesetengah API lama menerima data sebagai application/x-www-form-urlencoded. Untuk itu, gunakan cfhttpparam jenis formField. Setiap medan menjadi satu param:
<cfhttp url="https://api.contoh.com/hantar" method="post" result="resp">
<cfhttpparam type="formField" name="nama" value="Ali Abu">
<cfhttpparam type="formField" name="jumlah" value="150">
</cfhttp>
Apabila anda perlu menghantar fail, atau API meminta multipart/form-data, tambah atribut multipart="true". Semua medan formField kemudian digabungkan menjadi satu badan multipart, dan anda boleh lampirkan fail dengan type="file" dan atribut file yang menunjuk ke laluan fail. Atribut lama multiPartType sudah deprecated, jadi gunakan multipart sahaja.
Timeout, Redirect dan Pengendalian Ralat
Secara lalai throwOnError ialah false. Ini bermakna respons 4xx atau 5xx tidak membuang exception, sebaliknya ralat dimasukkan ke dalam struct result. Sentiasa semak kekunci ERROR dan statuscode sebelum meneruskan. Jika anda mahu exception terus dibuang supaya boleh ditangkap dengan cftry dan cfcatch, set throwOnError="true".
Atribut timeout menerima saat atau objek TimeSpan dan menjadi nilai sandaran untuk dua timeout yang lebih halus: connectionTimeout untuk fasa sambungan TCP, dan socketTimeout untuk menunggu data selepas sambungan dibuka. Kedua-duanya tersedia sejak Lucee 6.2.2.66. Atribut redirect mengawal pengikutan respons 3xx: secara lalai true dan mengikut sehingga 15 redirect, manakala false berhenti pada respons redirect pertama. Sejak Lucee 7.0.0.208, nilai Lax memulangkan filecontent untuk POST dan DELETE yang di-redirect:
<cftry>
<cfhttp url="https://api.contoh.com/data" method="get" result="resp"
timeout="10" connectionTimeout="5" socketTimeout="5"
redirect="false" throwOnError="true">
</cfhttp>
<cfcatch>
<cfoutput>Panggilan gagal: #cfcatch.message#</cfoutput>
</cfcatch>
</cftry>
Apabila tiada timeout dinyatakan, Lucee menggunakan baki timeout permintaan halaman semasa, jadi panggilan tidak akan melebihi masa hidup permintaan.
SSL dan Sijil Pelayan
Ralat sijil berlaku apabila pelayan sasaran menggunakan sijil yang ditandatangani sendiri atau CA peribadi yang tidak dikenali oleh truststore Java. Lucee menyediakan beberapa jalan keluar. Paling mudah ialah atribut autoCert="true" pada cfhttp, yang memasang sijil SSL untuk sambungan HTTPS secara automatik dan tersedia sejak Lucee 6.1.0.132.
Anda juga boleh memasang sijil untuk host tertentu dengan fungsi SSLCertificateInstall, yang memuat turun sijil daripada host dan memasangnya:
<cfscript>
SSLCertificateInstall("api.rakan.com", 443);
</cfscript>
<cfhttp url="https://api.rakan.com/data" method="get" result="resp" autoCert="true">
</cfhttp>
Sejak Lucee 6, enjin menggunakan fail cacerts JVM sebagai truststore lalai. Jika anda mahu Lucee kembali menggunakan truststore sendiri supaya fungsi SSLCertificateInstall menyimpan sijil ke tempat lama, hidupkan sifat sistem lucee.use.lucee.SSL.TrustStore atau pemboleh ubah persekitaran LUCEE_USE_LUCEE_SSL_TRUSTSTORE. Fungsi SSLCertificateInstall juga menerima cacertPath dan password untuk pangkalan sijil tersuai, kedua-duanya sejak Lucee 7.0.0.234.
Muat Turun Fail dan Cache Respons
cfhttp bukan sahaja untuk API yang memulangkan JSON. Untuk memuat turun fail binari, gunakan atribut getAsBinary. Nilai lalai false mengembalikan kandungan sebagai rentetan, nilai auto memulangkan binari apabila respons bukan teks, dan true sentiasa memulangkan binari. Anda kemudian menyimpannya dengan cffile:
<cfhttp url="https://contoh.com/dokumen.pdf" method="get" result="resp" getAsBinary="auto">
</cfhttp>
<cfif resp.ERROR eq "" AND left(resp.statusCode, 3) == "200">
<cffile action="write" file="#expandPath('./dokumen.pdf')#" output="#resp.fileContent#">
</cfif>
Untuk respons yang sama dipanggil berulang kali, atribut cachedWithin menerima nilai "request" atau objek TimeSpan untuk menyimpan respons dalam cache bagi tempoh itu. Ini mengurangkan panggilan keluar bagi data yang jarang berubah, walaupun untuk data sangat dinamik anda perlu kekalkan nilai lalai tanpa cache.
Pengesahan Asas dan Sijil Klien
Untuk API yang dilindungi HTTP Basic, isi atribut username dan password. Lucee menghantar kelayakan secara preemptive secara lalai kerana preAuth ialah true, dan authType menyokong BASIC (lalai) serta NTLM. Untuk pengesahan berasaskan sijil klien, atribut clientCert menunjuk ke fail PKCS12 dan clientCertPassword memegang kata laluannya:
<cfhttp url="https://api.contoh.com/rahsia" method="get" result="resp"
username="pengguna" password="laluan" authType="BASIC">
</cfhttp>
Data yang diterima daripada API luar ialah input tidak dipercayai. Sentiasa sahkan dan lepaskan nilai sebelum memaparkannya semula ke pelayar, kerana kandungan luar boleh menjadi vektor serangan yang dibincangkan dalam panduan keselamatan aplikasi web CFML. Untuk memudahkan penyiasatan masalah, rekod setiap panggilan yang gagal melalui mekanisme yang diterangkan dalam panduan log dan pemantauan.
Soalan Lazim (FAQ)
Kenapa API saya pulangkan 404 walaupun URL saya betul?
Cuba set encodeUrl="false". Secara lalai encodeUrl ialah true, dan Lucee mungkin mengekod semula parameter yang sudah dikekod, menghasilkan ralat 404 yang mengelirukan pada sesetengah API.
Kenapa tiada exception apabila pelayan pulangkan 500?
Kerana throwOnError lalai false. Ralat dimasukkan ke dalam struct result dan bukannya dibuang. Semak resp.statuscode dan kekunci ERROR, atau set throwOnError="true" untuk menerima exception.
Bagaimana cara menghantar fail bersama medan borang?
Guna atribut multipart="true" pada cfhttp, kemudian tambah cfhttpparam jenis file dengan atribut file yang menunjuk ke laluan fail, bersama medan formField yang lain.
Bagaimana cara memasang sijil SSL untuk pelayan dengan sijil sendiri?
Guna SSLCertificateInstall(host, port) untuk memasang sijil bagi host tertentu, atau tambah autoCert="true" pada cfhttp supaya sijil dipasang secara automatik.
Bolehkah cfhttp menghantar permintaan PUT atau DELETE?
Ya. Lucee menyokong semua kaedah HTTP secara natif termasuk PUT, DELETE, PATCH, HEAD dan OPTIONS, bukan sekadar GET dan POST.