PHP Request請求封裝

/**
 * Request請求封裝
 * Class Request
 * @package tool
 */
class Request
{

    // curl 請求錯誤碼
    protected static $list_errno = [
        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 鏈接'
    ];

    /**
     * curl模擬提交
     * @param $url
     * @param array $params
     * @param array $header
     * @param string $method
     * @param array $options
     * @return array|mixed
     */
    public static function curl_request($url, $params=[], $header=[], $method='post', $options=[])
    {

        if(!function_exists('curl_init')){
            return [
                'code' => 0,
                'msg' => 'Do not support CURL function.',
                'data' => [],
            ];
        }
        if(!filter_var($url, FILTER_VALIDATE_URL)){
            return [
                'code' => 0,
                'msg' => self::$list_errno[3],
                'data' => [],
            ];
        }
        unset($parts);

        // 請求參數格式轉換成數組
//        if('json' !== strtolower($method)){
//            $params = self::format_params($params);
//        }

        // 頭部格式轉換
        $header = self::format_header($header);

        // 參數格數轉換與請求頭設置
        switch (strtolower($method)){
            case 'get':
                $options[CURLOPT_POST] = false; //GET提交方式
                if(!empty($params)){
                    $params = is_array($params) ? http_build_query($params) : $params;
                    $url .= (strstr($url,'?') ? '&' : '?') . $params;
                    $params = [];
                }
                break;
            case 'post':
                $options[CURLOPT_POST] = true; //post提交方式
                break;
            case 'json':
                $options[CURLOPT_POST] = true; //post提交方式

                if(!empty($params) && is_array($params)) $params = json_encode($params);
                if(!is_array($header)) $header = [];
                $check = false;
                if(!empty($header)){
                    foreach ($header as $value){
                        if(false !== stripos($value,'application/json')){
                            $check = true;
                            break;
                        }
                    }
                }
                if(!$check){
                    if(!empty($params)){
                        array_unshift($header, 'Content-Length: '.strlen($params));
                    }
                    array_unshift($header, 'Accept: application/json');
                    array_unshift($header, 'Content-Type: application/json; charset=utf-8');
                }
                break;
            case 'form':
                $options[CURLOPT_POST] = true; //post提交方式
                // 僞造來源referer
                if(!isset($options[CURLOPT_REFERER])){
                    $options[CURLOPT_REFERER] = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $_SERVER['REQUEST_SCHEME'] . '://'. $_SERVER['HTTP_HOST'];
                }

                if(!empty($params) && is_array($params)) $params = http_build_query($params);
                if(!is_array($header)) $header = [];
                $check = false;
                if(!empty($header)){
                    foreach ($header as $value){
                        if(false !== stripos($value,'application/x-www-form-urlencoded')){
                            $check = true;
                            break;
                        }
                    }
                }
                if(!$check){
                    if(!empty($params)){
                        array_unshift($header, 'Content-Length: '.strlen($params));
                    }
                    array_unshift($header, 'Content-Type: application/x-www-form-urlencoded; charset=utf-8');
                }
                break;
            default:
                $options[CURLOPT_POST] = true; //post提交方式
        }

        $ch = curl_init(); //初始化curl

        $setopt = [];
        if(false !== stripos($url,'https://')){
            $setopt[CURLOPT_SSL_VERIFYPEER] = false; // 禁止curl驗證證書
            $setopt[CURLOPT_SSL_VERIFYHOST] = false; // 禁止檢測主機
            $setopt[CURLOPT_SSLVERSION] = true; // CURL_SSLVERSION_TLSv1
        }
        $setopt[CURLOPT_URL] = $url; //抓取指定網頁
        $setopt[CURLOPT_POST] = true; //是否POST提交方式
        $setopt[CURLOPT_USERAGENT] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'; //模擬瀏覽器代理
        $setopt[CURLOPT_RETURNTRANSFER] = true; //設置獲取的信息以文件流的形式返回,而不是直接輸出
        $setopt[CURLOPT_NOBODY] = false; //不顯示body
        $setopt[CURLOPT_HEADER] = false; //設置頭文件的信息做爲數據流輸出

//        $header[] = 'CLIENT-IP: 8.8.8.8';
//        $header[] = 'X-FORWARDED-FOR: 8.8.8.8'; // 僞造IP來源

        if(!empty($header)){
            $setopt[CURLOPT_HTTPHEADER] = $header; //請求頭設置
        }

//        $setopt[CURLOPT_REFERER] = 60; //僞造來源referer

//        $setopt[CURLOPT_CONNECTTIMEOUT] = 60; //超時設置
//        $setopt[CURLOPT_FOLLOWLOCATION] = true; //根據服務器返回 HTTP 頭中的'Location:'重定向
//        $setopt[CURLOPT_MAXREDIRS] = 3; //最大重定向次數

//        $setopt[CURLOPT_HTTPPROXYTUNNEL] = true; //是否經過http代理來傳輸
//        $setopt[CURLOPT_PROXY] = 'ip:端口號'; //是否經過http代理來傳輸
//        $setopt[CURLOPT_PROXYUSERPWD] = 'user:password'; //若是要密碼的話,加上這個

        // cookie設置
//        $setopt[CURLOPT_COOKIE] = ''; //cookie

        //curl上傳或者下載,獲取curl傳輸進度
//        $setopt[CURLOPT_NOPROGRESS] = false; //是否關閉傳輸進度,默認是true
//        $setopt[CURLOPT_PROGRESSFUNCTION] = 'callback'; //回調函數,curl傳輸過程當中,會每隔一段時間自動調用該函數

        if(!empty($params)){
            $setopt[CURLOPT_POSTFIELDS] = $params; //提交數據
        }
        if (function_exists('curl_file_create')){ // php >= 5.5
            $setopt[CURLOPT_SAFE_UPLOAD] = true; //文件上傳
        }else {
            if (defined('CURLOPT_SAFE_UPLOAD')){
                $setopt[CURLOPT_SAFE_UPLOAD] = false; //文件上傳
            }
        }
        if(!empty($options) && is_array($options)) $setopt = $options + $setopt;

        curl_setopt_array($ch, $setopt);
        unset($url, $params, $header, $method, $setopt);

        $response = curl_exec($ch); //運行curl
        $errno = curl_errno($ch); //返回最後一次的錯誤號
        $http_code = curl_getinfo($ch,CURLINFO_HTTP_CODE); //狀態碼
        curl_close($ch);

        if (0 !== $errno) {
            return [
                'code' => 0,
                'msg'   => isset(self::$list_errno[$errno]) ? self::$list_errno[$errno] : $errno,
                'data'  => $response,
            ];
        }

        try {
            $result = json_decode($response,true) ?: (200 === $http_code ? $response : ['code' => 0, 'msg' => "請求狀態碼爲:{$http_code}", 'data' => $response]);
        } catch (\Exception $e) {
            $result = $response;
        }

        unset($response, $errno, $http_code);

        return $result;
    }

    /**
     * get提交
     * @param $url
     * @param array $params
     * @param array $header
     * @param int $timeout
     * @return mixed
     */
    public static function get($url, $params=[], $header=[], $timeout=60)
    {

        $response = self::curl_request($url, $params, $header, 'get', [CURLOPT_CONNECTTIMEOUT => $timeout]);

        unset($url, $params, $header, $timeout);

        return $response;
    }

    /**
     * post提交
     * @param $url
     * @param array $params
     * @param array $header
     * @param int $timeout
     * @return mixed
     */
    public static function post($url, $params=[], $header=[], $timeout=60)
    {

        $response = self::curl_request($url, $params, $header, 'post', [CURLOPT_CONNECTTIMEOUT => $timeout]);

        unset($url, $params, $header, $timeout);

        return $response;
    }

    /**
     * json提交
     * @param $url
     * @param array $params
     * @param array $header
     * @param int $timeout
     * @return mixed
     */
    public static function json($url, $params=[], $header=[], $timeout=60)
    {

        $response = self::curl_request($url, $params, $header, 'json', [CURLOPT_CONNECTTIMEOUT => $timeout]);

        unset($url, $params, $header, $timeout);

        return $response;
    }

    /**
     * form表單提交
     * @param $url
     * @param array $params
     * @param array $header
     * @param int $timeout
     * @return array|mixed
     */
    public static function form($url, $params=[], $header=[], $timeout=60){

        $response = self::curl_request($url, $params, $header, 'form', [CURLOPT_CONNECTTIMEOUT => $timeout]);

        unset($url, $params, $header, $timeout);

        return $response;
    }


    /**
     * 組裝form表單跳轉
     * @param $url
     * @param $params
     * @param string $method
     */
    public static function createForm($url, $params, $method='post'){
        $html = '<!doctype html>';
        $html .= '<html>';
        $html .= '<head>';
        $html .= '<meta charset="utf8">';
        $html .= '<title>正在跳轉...</title>';
        $html .= '</head>';
        $html .= '<body onLoad="document.form.submit()">';
        $html .= '<form action="' . $url . '" method="' . $method . '" name="form">';
        if(is_array($params) && !empty($params)){
            foreach ($params as $key=>$value){
                $html .= '<input type="hidden" name="' . $key . '" value="' . $value . '">';
            }
        }
        $html .= '</form>';
        $html .= '</body>';
        $html .= '</html>';

        return $html;
    }
相關文章
相關標籤/搜索