PHP CURL詳解

reggie發表於2021-07-14

CURL是一個功能強大的開源類庫.

簡介

PHP 支援 Daniel Stenberg 建立的 libcurl 庫,能夠連線通訊各種伺服器、使用各種協議。libcurl 目前支援的協議有 http、https、ftp、gopher、telnet、dict、file、ldap。 libcurl 同時支援 HTTPS 證照、HTTP POST、HTTP PUT、 FTP 上傳(也能透過 PHP 的 FTP 擴充套件完成)、HTTP 基於表單的上傳、代理、cookies、使用者名稱+密碼的認證。官方連結

使用

我們在使用CURL完成一個請求的時候一般需要下面幾個步驟。

設定連線控制程式碼

這裡主要使用 curl_init() 函式

curl_init ([ string $url = NULL ] ) : resource

引數url不是必填項,用來初始化新的會話,返回cURL控制程式碼,失敗了返回false。

設定相關屬性選項

主要使用 curl_setopt() 函式和 curl_setopt_array() 函式

/**
 * 設定cURL傳輸選項
 * 
 * @param resource $ch 初始化的cURL控制程式碼
 * @param int $option 設定的引數選項名稱
 * @param mixed $value 要設定的值
 * @return bool 成功返回true 失敗返回false
 */
function curl_setopt( resource $ch , int $option , mixed $value )

/**
 * 批次設定cURL傳輸選項
 * 
 * @param resource $ch 初始化的cURL控制程式碼
 * @param array $option 設定的選項陣列,包含選項名和值
 * @return bool 成功返回true 失敗返回false
 */
function curl_setopt_array( resource $ch , array $option )

其中可以設定的選項很多,具體的可以看官方這裡中文這裡

常用的如下:

CURLOPT_URL: 設定請求的地址

CURLOPT_HEADER:設定請求header頭資訊,比如授權token啦,編碼啦,格式啦之類.

CURLOPT_CUSTOMREQUEST: 設定請求方式 比如 get post head options之類

CURLOPT_TIMEOUT:設定執行的最大時間

CURLOPT_CONNECTTIMEOUT:設定發起連線前等待的時間

CURLOPT_USERAGENT:設定useragent資訊

CURLOPT_PORT:設定埠資訊

CURLOPT_COOKIE:設定http請求中的cookie資訊(parameA=aaa;parameB=bbb)

CURLOPT_POSTFIELDS:如果是post請求設定的請求引數

執行獲取結果

主要使用 curl_exec() 函式.這個函式應該在初始化一個 cURL 會話並且全部的選項都被設定後被呼叫。

/**
 * 執行 cURL 會話
 * 
 * @param resource $ch 初始化的cURL控制程式碼
 * @return mixed 成功時返回 TRUE, 或者在失敗時返回 FALSE。 然而,如果 設定了 CURLOPT_RETURNTRANSFER 選項,函式執行成功時會返回執行的結果,失敗時返回 FALSE 。 
 */
function curl_exec( resource $ch )

關閉連線控制程式碼

主要使用 curl_close() 函式

/**
 * 執行 cURL 會話
 * 
 * @param resource $ch 初始化的cURL控制程式碼
 * @return void 沒有返回值
 */
function curl_close( resource $ch )

錯誤碼

在獲取執行結果的時候有時候會失敗,這個獲取錯誤碼就很重要了。

/**
 * 執返回最後一次的錯誤程式碼
 * 
 * @param resource $ch 初始化的cURL控制程式碼
 * @return int 操作的錯誤程式碼。 
 */
function curl_errno(resource $ch)

之前常遇到過的錯誤碼有

5:CURLE_COULDNT_RESOLVE_PROXY = 指定的代理伺服器主機無法解析

6:CURLE_COULDNT_RESOLVE_HOST = 指定的遠端主機無法解析

28:CURLE_OPERATION_TIMEDOUT = 已達到根據相應情況指定的超時時間

33:CURLE_RANGE_ERROR = 伺服器不支援或不接受範圍請求

56:CURLE_RECV_ERROR = 接收網路資料失敗

更多錯誤碼 中文這裡

'1'=>'CURLE_UNSUPPORTED_PROTOCOL (1) – 您傳送給 libcurl 的網址使用了此 libcurl 不支援的協議。 可能是您沒有使用的編譯時選項造成了這種情況(可能是協議字串拼寫有誤,或沒有指定協議 libcurl 程式碼)。',
'2'=>'CURLE_FAILED_INIT (2) – 非常早期的初始化程式碼失敗。 可能是內部錯誤或問題。',
'3'=>'CURLE_URL_MALFORMAT (3) – 網址格式不正確。',
'5'=>'CURLE_COULDNT_RESOLVE_PROXY (5) – 無法解析代理伺服器。 指定的代理伺服器主機無法解析。',
'6'=>'CURLE_COULDNT_RESOLVE_HOST (6) – 無法解析主機。 指定的遠端主機無法解析。',
'7'=>'CURLE_COULDNT_CONNECT (7) – 無法透過 connect() 連線至主機或代理伺服器。',
'8'=>'CURLE_FTP_WEIRD_SERVER_REPLY (8) – 在連線到 FTP 伺服器後,libcurl 需要收到特定的回覆。 此錯誤程式碼表示收到了不正常或不正確的回覆。 指定的遠端伺服器可能不是正確的 FTP 伺服器。',
'9'=>'CURLE_REMOTE_ACCESS_DENIED (9) – 我們無法訪問網址中指定的資源。 對於 FTP,如果嘗試更改為遠端目錄,就會發生這種情況。',
'11'=>'CURLE_FTP_WEIRD_PASS_REPLY (11) – 在將 FTP 密碼傳送到伺服器後,libcurl 需要收到正確的回覆。 此錯誤程式碼表示返回的是意外的程式碼。',
'13'=>'CURLE_FTP_WEIRD_PASV_REPLY (13) – libcurl 無法從伺服器端收到有用的結果,作為對 PASV 或 EPSV 命令的響應。 伺服器有問題。',
'14'=>'CURLE_FTP_WEIRD_227_FORMAT (14) – FTP 伺服器返回 227 行作為對 PASV 命令的響應。如果 libcurl 無法解析此行,就會返回此程式碼。',
'15'=>'CURLE_FTP_CANT_GET_HOST (15) – 在查詢用於新連線的主機時出現內部錯誤。',
'17'=>'CURLE_FTP_COULDNT_SET_TYPE (17) – 在嘗試將傳輸模式設定為二進位制或 ascii 時發生錯誤。',
'18'=>'CURLE_PARTIAL_FILE (18) – 檔案傳輸尺寸小於或大於預期。當伺服器先報告了一個預期的傳輸尺寸,然後所傳送的資料與先前指定尺寸不相符時,就會發生此錯誤。',
'19'=>'CURLE_FTP_COULDNT_RETR_FILE (19) – ‘RETR’ 命令收到了不正常的回覆,或完成的傳輸尺寸為零位元組。',
'21'=>'CURLE_QUOTE_ERROR (21) – 在向遠端伺服器傳送自定義 “QUOTE” 命令時,其中一個命令返回的錯誤程式碼為 400 或更大的數字(對於 FTP),或以其他方式表明命令無法成功完成。',
'22'=>'CURLE_HTTP_RETURNED_ERROR (22) – 如果 CURLOPT_FAILONERROR 設定為 TRUE,且 HTTP 伺服器返回 >= 400 的錯誤程式碼,就會返回此程式碼。 (此錯誤程式碼以前又稱為 CURLE_HTTP_NOT_FOUND。)',
'23'=>'CURLE_WRITE_ERROR (23) – 在向本地檔案寫入所收到的資料時發生錯誤,或由寫入回撥 (write callback) 向 libcurl 返回了一個錯誤。',
'25'=>'CURLE_UPLOAD_FAILED (25) – 無法開始上傳。 對於 FTP,伺服器通常會拒絕執行 STOR 命令。錯誤緩衝區通常會提供伺服器對此問題的說明。 (此錯誤程式碼以前又稱為 CURLE_FTP_COULDNT_STOR_FILE。)',
'26'=>'CURLE_READ_ERROR (26) – 讀取本地檔案時遇到問題,或由讀取回撥 (read callback) 返回了一個錯誤。',
'27'=>'CURLE_OUT_OF_MEMORY (27) – 記憶體分配請求失敗。此錯誤比較嚴重,若發生此錯誤,則表明出現了非常嚴重的問題。',
'28'=>'CURLE_OPERATION_TIMEDOUT (28) – 操作超時。 已達到根據相應情況指定的超時時間。',
'30'=>'CURLE_FTP_PORT_FAILED (30) – FTP PORT 命令返回錯誤。 在沒有為 libcurl 指定適當的地址使用時,最有可能發生此問題。 請參閱 CURLOPT_FTPPORT。',
'31'=>'CURLE_FTP_COULDNT_USE_REST (31) – FTP REST 命令返回錯誤。如果伺服器正常,則應當不會發生這種情況。',
'33'=>'CURLE_RANGE_ERROR (33) – 伺服器不支援或不接受範圍請求。',
'34'=>'CURLE_HTTP_POST_ERROR (34) – 此問題比較少見,主要由內部混亂引發。',
'35'=>'CURLE_SSL_CONNECT_ERROR (35) – 同時使用 SSL/TLS 時可能會發生此錯誤。您可以訪問錯誤緩衝區檢視相應資訊,其中會對此問題進行更詳細的介紹。可能是證照(檔案格式、路徑、許可)、密碼及其他因素導致了此問題。',
'36'=>'CURLE_FTP_BAD_DOWNLOAD_RESUME (36) – 嘗試恢復超過檔案大小限制的 FTP 連線。',
'37'=>'CURLE_FILE_COULDNT_READ_FILE (37) – 無法開啟 FILE:// 路徑下的檔案。原因很可能是檔案路徑無法識別現有檔案。 建議您檢查檔案的訪問許可權。',
'38'=>'CURLE_LDAP_CANNOT_BIND (38) – LDAP 無法繫結。LDAP 繫結操作失敗。',
'39'=>'CURLE_LDAP_SEARCH_FAILED (39) – LDAP 搜尋無法進行。',
'41'=>'CURLE_FUNCTION_NOT_FOUND (41) – 找不到函式。 找不到必要的 zlib 函式。',
'42'=>'CURLE_ABORTED_BY_CALLBACK (42) – 由回撥中止。 回撥向 libcurl 返回了 “abort”。',
'43'=>'CURLE_BAD_FUNCTION_ARGUMENT (43) – 內部錯誤。 使用了不正確的引數呼叫函式。',
'45'=>'CURLE_INTERFACE_FAILED (45) – 介面錯誤。 指定的外部介面無法使用。 請透過 CURLOPT_INTERFACE 設定要使用哪個介面來處理外部連線的來源 IP 地址。 (此錯誤程式碼以前又稱為 CURLE_HTTP_PORT_FAILED。)',
'47'=>'CURLE_TOO_MANY_REDIRECTS (47) – 重定向過多。 進行重定向時,libcurl 達到了網頁點選上限。請使用 CURLOPT_MAXREDIRS 設定上限。',
'48'=>'CURLE_UNKNOWN_TELNET_OPTION (48) – 無法識別以 CURLOPT_TELNETOPTIONS 設定的選項。 請參閱相關文件。',
'49'=>'CURLE_TELNET_OPTION_SYNTAX (49) – telnet 選項字串的格式不正確。',
'51'=>'CURLE_PEER_FAILED_VERIFICATION (51) – 遠端伺服器的 SSL 證照或 SSH md5 指紋不正確。',
'52'=>'CURLE_GOT_NOTHING (52) – 伺服器未返回任何資料,在相應情況下,未返回任何資料就屬於出現錯誤。',
'53'=>'CURLE_SSL_ENGINE_NOTFOUND (53) – 找不到指定的加密引擎。',
'54'=>'CURLE_SSL_ENGINE_SETFAILED (54) – 無法將選定的 SSL 加密引擎設為預設選項。',
'55'=>'CURLE_SEND_ERROR (55) – 無法傳送網路資料。',
'56'=>'CURLE_RECV_ERROR (56) – 接收網路資料失敗。',
'58'=>'CURLE_SSL_CERTPROBLEM (58) – 本地客戶端證照有問題',
'59'=>'CURLE_SSL_CIPHER (59) – 無法使用指定的金鑰',
'60'=>'CURLE_SSL_CACERT (60) – 無法使用已知的 CA 證照驗證對等證照',
'61'=>'CURLE_BAD_CONTENT_ENCODING (61) – 無法識別傳輸編碼',
'62'=>'CURLE_LDAP_INVALID_URL (62) – LDAP 網址無效',
'63'=>'CURLE_FILESIZE_EXCEEDED (63) – 超過了檔案大小上限',
'64'=>'CURLE_USE_SSL_FAILED (64) – 請求的 FTP SSL 級別失敗',
'65'=>'CURLE_SEND_FAIL_REWIND (65) – 進行傳送操作時,curl 必須迴轉資料以便重新傳輸,但迴轉操作未能成功',
'66'=>'CURLE_SSL_ENGINE_INITFAILED (66) – SSL 引擎初始化失敗',
'67'=>'CURLE_LOGIN_DENIED (67) – 遠端伺服器拒絕 curl 登入(7.13.1 新增功能)',
'68'=>'CURLE_TFTP_NOTFOUND (68) – 在 TFTP 伺服器上找不到檔案',
'69'=>'CURLE_TFTP_PERM (69) – 在 TFTP 伺服器上遇到許可權問題',
'70'=>'CURLE_REMOTE_DISK_FULL (70) – 伺服器磁碟空間不足',
'71'=>'CURLE_TFTP_ILLEGAL (71) – TFTP 操作非法',
'72'=>'CURLE_TFTP_UNKNOWNID (72) – TFTP 傳輸 ID 未知',
'73'=>'CURLE_REMOTE_FILE_EXISTS (73) – 檔案已存在,無法覆蓋',
'74'=>'CURLE_TFTP_NOSUCHUSER (74) – 執行正常的 TFTP 伺服器不會返回此錯誤',
'75'=>'CURLE_CONV_FAILED (75) – 字元轉換失敗',
'76'=>'CURLE_CONV_REQD (76) – 呼叫方必須註冊轉換回撥',
'77'=>'CURLE_SSL_CACERT_BADFILE (77) – 讀取 SSL CA 證照時遇到問題(可能是路徑錯誤或訪問許可權問題)',
'78'=>'CURLE_REMOTE_FILE_NOT_FOUND (78) – 網址中引用的資源不存在',
'79'=>'CURLE_SSH (79) – SSH 會話中發生無法識別的錯誤',
'80'=>'CURLE_SSL_SHUTDOWN_FAILED (80) – 無法終止 SSL 連線'

英文原版錯誤碼見 這裡

設定代理

對於一些牆外的請求需要設定一下代理,本地有 Shadowsocks 之類工具的可以這樣設定

curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 跳過證照檢查
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);  // 從證照中檢查SSL加密演算法是否存在
// 設定本地代理
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 設定不直接輸出結果,而是儲存到exec的結果中
curl_setopt($curl,CURLOPT_PROXY, '127.0.0.1');
curl_setopt($curl,CURLOPT_PROXYPORT, '1080'); // 這個是代理的埠
curl_setopt ($curl, CURLOPT_TIMEOUT, 30);

SS原理見 這裡

本作品採用《CC 協議》,轉載必須註明作者和本文連結
微信公眾號:碼咚沒 ( ID: codingdongmei )

相關文章