CURL模拟网络请求
@param string $method 请求方法
@param string $url 请求方法
@param array $options 请求参数[headers,data,ssl_cer,ssl_key]
@return boolean|string
@throws LocalCacheException
188866
public static function doRequest($method, $url, $options = [])
    {
        $curl = curl_init();
        // GET参数设置
        if (!empty($options['query'])) {
            $url .= (stripos($url, '?') !== false ? '&' : '?') . http_build_query($options['query']);
        }
        // CURL头信息设置
        if (!empty($options['headers'])) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $options['headers']);
        }
        // POST数据设置
        if (strtolower($method) === 'post') {
            curl_setopt($curl, CURLOPT_POST, true);
            curl_setopt($curl, CURLOPT_POSTFIELDS, self::_buildHttpData($options['data']));
        }
        // 证书文件设置
        if (!empty($options['ssl_cer'])) if (file_exists($options['ssl_cer'])) {
            curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
            curl_setopt($curl, CURLOPT_SSLCERT, $options['ssl_cer']);
        } else throw new InvalidArgumentException("Certificate files that do not exist. --- [ssl_cer]");
        // 证书文件设置
        if (!empty($options['ssl_key'])) if (file_exists($options['ssl_key'])) {
            curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');
            curl_setopt($curl, CURLOPT_SSLKEY, $options['ssl_key']);
        } else throw new InvalidArgumentException("Certificate files that do not exist. --- [ssl_key]");
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_TIMEOUT, 60);
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        list($content) = [curl_exec($curl), curl_close($curl)];
        // 清理 CURL 缓存文件
        if (!empty(self::$cache_curl)) foreach (self::$cache_curl as $key => $file) {
            Tools::delCache($file);
            unset(self::$cache_curl[$key]);
        }
        return $content;
    }
625913
protected function buildRequest(string $method, string $url, array $options = []): array
    {
        if ($this->forcedAcceptJson) {
            $this->headers['accept'] = 'application/json';
        }
        if (count($this->headers) > 0) {
            if (!array_key_exists(RequestOptions::HEADERS, $options) || !is_array($options[RequestOptions::HEADERS])) {
                $options[RequestOptions::HEADERS] = [];
            }
            foreach ($this->headers as $headerName => $headerValue) {
                $options[RequestOptions::HEADERS][$headerName] = $headerValue;
            }
        }

        $options = $this->addAuthHeader($options);

        return [
            self::OPTION_METHOD => $method,
            self::OPTION_URL => $this->buildUrl($url),
            self::OPTION_OPTIONS => $options
        ];
    }
1357776
public function requestAsync($method, $url, $options)
    {
        $request = $this->authClient->getAuthenticatedRequest($method, $url, $this->getAccessToken());

        return $this->httpClient->sendAsync($request, $options);
    }
1179912
protected function request($uri, $method = 'get', $options = array())
    {
        $this->clear();

        if (! in_array(strtolower($method), $this->methods)) {
            return $this->setError('Unknown request method: ' . $method);
        }

        $isAuthorized = $this->accessToken || $this->token ||
                        ($this->username && $this->password);

        if (! $isAuthorized) {
            return $this->setError('Please provide token or username and password');
        }

        // if uri is passed as array, create uri string from uri parts
        if (is_array($uri)) {
            $uri = implode('/', $uri);
        }

        // api request url
        $url = $this->endpoint . $uri;

        $handle = curl_init();

        if ($this->accessToken) {
            // Access token is used in OAuth2 flow
            $url .= '?access_token=' . $this->accessToken;
        } else if ($this->token) {
            // Auth token is taken from PG account
            $url .= '?auth_token=' . $this->token;
        } else {
            // if using username and password - pass them as curl option
            curl_setopt($handle, CURLOPT_USERPWD, $this->username . ':' . $this->password);
        }

        curl_setopt($handle, CURLOPT_URL, $url);
        curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($handle, CURLOPT_CUSTOMREQUEST, strtoupper($method));
        curl_setopt($handle, CURLOPT_HTTPHEADER, array(
            'Content-type: multipart/form-data;',
        ));

        // if request has additional options - add them to request
        if (! empty($options)) {

            // extract files, pass them separately
            $files = array();
            foreach ($options as $key => $value) {
                if (! empty($value) && ! is_array($value) && $value[0] === '@') {
                    $files[$key] = $this->toCurlFile($value);
                    unset($options[$key]);
                }
            }

            $data = $files;

            if (! empty($options)) {
                // original API requires data to be in json format
                $data = array_merge($data, array(
                    'data' => json_encode($options),
                ));
            }

            curl_setopt($handle, CURLOPT_POSTFIELDS, $data);
        }

        $response = curl_exec($handle);

        if (curl_errno($handle)) {
            $this->setError(curl_error($handle));
            curl_close($handle);
            return false;
        }

        // get httd code to identify if request was successful
        $httpcode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
        $this->success = in_array($httpcode, $this->codes);

        curl_close($handle);

        $decoded = json_decode($response, true);

        // request may be successful, but also can have errors, for example, about keys
        if (isset($decoded['error']) && $error = $decoded['error']) {
            if (is_array($error)) {
                $error = $this->assocToString($error);
            }
            $this->setError($error);
        }

        if (! $this->success) {
            return false;
        }

        return $decoded;
    }
667809
private function performRequest($method, $url, $options) {

        try {
            switch ($method) {
                case 'GET':
                    return json_decode($this->client->get($url, $options)->getBody(), true);
                case 'POST':
                    return json_decode($this->client->post($url, $options)->getBody(), true);
                case 'PUT':
                    return json_decode($this->client->put($url, $options)->getBody(), true);
                case 'DELETE':
                    return json_decode($this->client->delete($url, $options)->getBody(), true);
                default:
                    return null;
            }
        } catch (RequestException $e) {
            throw ApiException::create($e);
        }
    }
584252
public static function curlGet($url = '', $options = array())
    {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
437434
protected function request($url, $options = array()) {
        // Reset here so that the data is valid when result returned from cache, or if we return due to a blacklist hit.
        $this->reset_request_state_vars();

        if ((defined('PHPUNIT_TEST') && PHPUNIT_TEST)) {
            if ($mockresponse = array_pop(self::$mockresponses)) {
                $this->info = [ 'http_code' => 200 ];
                return $mockresponse;
            }
        }

        // If curl security is enabled, check the URL against the blacklist before calling curl_exec.
        // Note: This will only check the base url. In the case of redirects, the blacklist is also after the curl_exec.
        if (!$this->ignoresecurity && $this->securityhelper->url_is_blocked($url)) {
            $this->error = $this->securityhelper->get_blocked_url_string();
            return $this->error;
        }

        // Set the URL as a curl option.
        $this->setopt(array('CURLOPT_URL' => $url));

        // Create curl instance.
        $curl = curl_init();

        $this->apply_opt($curl, $options);
        if ($this->cache && $ret = $this->cache->get($this->options)) {
            return $ret;
        }

        $ret = curl_exec($curl);
        $this->info  = curl_getinfo($curl);
        $this->error = curl_error($curl);
        $this->errno = curl_errno($curl);
        // Note: $this->response and $this->rawresponse are filled by $hits->formatHeader callback.

        // In the case of redirects (which curl blindly follows), check the post-redirect URL against the blacklist entries too.
        if (intval($this->info['redirect_count']) > 0 && !$this->ignoresecurity
            && $this->securityhelper->url_is_blocked($this->info['url'])) {
            $this->reset_request_state_vars();
            $this->error = $this->securityhelper->get_blocked_url_string();
            curl_close($curl);
            return $this->error;
        }

        if ($this->emulateredirects and $this->options['CURLOPT_FOLLOWLOCATION'] and $this->info['http_code'] != 200) {
            $redirects = 0;

            while($redirects <= $this->options['CURLOPT_MAXREDIRS']) {

                if ($this->info['http_code'] == 301) {
                    // Moved Permanently - repeat the same request on new URL.

                } else if ($this->info['http_code'] == 302) {
                    // Found - the standard redirect - repeat the same request on new URL.

                } else if ($this->info['http_code'] == 303) {
                    // 303 See Other - repeat only if GET, do not bother with POSTs.
                    if (empty($this->options['CURLOPT_HTTPGET'])) {
                        break;
                    }

                } else if ($this->info['http_code'] == 307) {
                    // Temporary Redirect - must repeat using the same request type.

                } else if ($this->info['http_code'] == 308) {
                    // Permanent Redirect - must repeat using the same request type.

                } else {
                    // Some other http code means do not retry!
                    break;
                }

                $redirects++;

                $redirecturl = null;
                if (isset($this->info['redirect_url'])) {
                    if (preg_match('|^https?://|i', $this->info['redirect_url'])) {
                        $redirecturl = $this->info['redirect_url'];
                    }
                }
                if (!$redirecturl) {
                    foreach ($this->response as $k => $v) {
                        if (strtolower($k) === 'location') {
                            $redirecturl = $v;
                            break;
                        }
                    }
                    if (preg_match('|^https?://|i', $redirecturl)) {
                        // Great, this is the correct location format!

                    } else if ($redirecturl) {
                        $current = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL);
                        if (strpos($redirecturl, '/') === 0) {
                            // Relative to server root - just guess.
                            $pos = strpos('/', $current, 8);
                            if ($pos === false) {
                                $redirecturl = $current.$redirecturl;
                            } else {
                                $redirecturl = substr($current, 0, $pos).$redirecturl;
                            }
                        } else {
                            // Relative to current script.
                            $redirecturl = dirname($current).'/'.$redirecturl;
                        }
                    }
                }

                curl_setopt($curl, CURLOPT_URL, $redirecturl);
                $ret = curl_exec($curl);

                $this->info  = curl_getinfo($curl);
                $this->error = curl_error($curl);
                $this->errno = curl_errno($curl);

                $this->info['redirect_count'] = $redirects;

                if ($this->info['http_code'] === 200) {
                    // Finally this is what we wanted.
                    break;
                }
                if ($this->errno != CURLE_OK) {
                    // Something wrong is going on.
                    break;
                }
            }
            if ($redirects > $this->options['CURLOPT_MAXREDIRS']) {
                $this->errno = CURLE_TOO_MANY_REDIRECTS;
                $this->error = 'Maximum ('.$this->options['CURLOPT_MAXREDIRS'].') redirects followed';
            }
        }

        if ($this->cache) {
            $this->cache->set($this->options, $ret);
        }

        if ($this->debug) {
            echo '<h1>Return Data</h1>';
            var_dump($ret);
            echo '<h1>Info</h1>';
            var_dump($this->info);
            echo '<h1>Error</h1>';
            var_dump($this->error);
        }

        curl_close($curl);

        if (empty($this->error)) {
            return $ret;
        } else {
            return $this->error;
            // exception is not ajax friendly
            //throw new moodle_exception($this->error, 'curl');
        }
    }
138019
public function sendRequest(
        MethodInterface $method,
        $requestMethod,
        $url,
        array $options = []
    ) {
        try {
            $response = $this->client->request($requestMethod, $url, $options);
            return json_decode($response->getBody(), true);
        } catch (ClientException $e) {
            throw $this->mapper->get($e, $method);
        } catch (\Exception $e) {
            throw new Exception\UnexpectedError('Unexpected error', $e->getCode(), $e);
        }
    }
1156013
protected function _curl($url,$options) {
		$curl=curl_init($url);
		curl_setopt($curl,CURLOPT_FOLLOWLOCATION,
			$options['follow_location']);
		curl_setopt($curl,CURLOPT_MAXREDIRS,
			$options['max_redirects']);
		curl_setopt($curl,CURLOPT_CUSTOMREQUEST,$options['method']);
		if (isset($options['header']))
			curl_setopt($curl,CURLOPT_HTTPHEADER,$options['header']);
		if (isset($options['content']))
			curl_setopt($curl,CURLOPT_POSTFIELDS,$options['content']);
		curl_setopt($curl,CURLOPT_ENCODING,'gzip,deflate');
		$timeout=isset($options['timeout'])?
			$options['timeout']:
			ini_get('default_socket_timeout');
		curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,$timeout);
		curl_setopt($curl,CURLOPT_TIMEOUT,$timeout);
		$headers=array();
		curl_setopt($curl,CURLOPT_HEADERFUNCTION,
			// Callback for response headers
			function($curl,$line) use(&$headers) {
				if ($trim=trim($line))
					$headers[]=$trim;
				return strlen($line);
			}
		);
		curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,FALSE);
		ob_start();
		curl_exec($curl);
		curl_close($curl);
		$body=ob_get_clean();
		return array(
			'body'=>$body,
			'headers'=>$headers,
			'engine'=>'cURL',
			'cached'=>FALSE
		);
	}
1100460
private static function curl($options = array()) {
    $curlOptions = array();
    $curl = curl_init();

    $curlOptions[CURLOPT_URL] = $options["url"];
    $curlOptions[CURLOPT_RETURNTRANSFER] = true;

    if ($options["method"] != "GET") {
      if ($options["method"] != "POST") {
        $curlOptions[CURLOPT_CUSTOMREQUEST] = $options["method"];
      }
      $curlOptions[CURLOPT_POSTFIELDS] = $options["body"];
      $curlOptions[CURLOPT_POST] = true;
    } else {
      $curlOptions[CURLOPT_HTTPGET] = true;
    }

    if (Api::getEnv() == "test") {
      $curlOptions[CURLOPT_VERBOSE] = true;
      $curlOptions[CURLOPT_SSL_VERIFYHOST] = false;
      $curlOptions[CURLOPT_SSL_VERIFYPEER] = false;
    }

    $curlOptions[CURLOPT_HTTPHEADER] = $options["headers"];
    curl_setopt_array($curl, $curlOptions);

    $responseJson = curl_exec($curl);
    $responseStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    $curlErrorCode = curl_errno($curl);
    $curlErrorMessage = curl_error($curl);
    curl_close($curl);

    return array(
      "body" => $responseJson,
      "status" => $responseStatus,
      "errorCode" => $curlErrorCode,
      "errorMessage" => $curlErrorMessage
    );
  }
132425
public function request($method, $uri, array $parameters = [], array $options = [])
    {
        $parameters['key'] = $this->apiKey;
        $options['query'] = $parameters;

        $uri = $this->apiUrl.$uri.'/json';

        $this->log($method, $uri, $options);
        $response = $this->httpClient->request($method, $uri, $options);

        $result = $this->decoder->decode($response);

        if (!isset($result['status'])) {
            throw new ClientErrorException('Missing return status');
        }

        if (!in_array($result['status'], [
                'OK',
                'ZERO_RESULTS',
            ], true)) {
            throw new ClientErrorException(sprintf('Invalid return status "%s"', $result['status']));
        }

        return $result;
    }
1025859
protected function exec(Url $url, array $options)
    {
        $connection = curl_init((string) $url);
        curl_setopt_array($connection, $options);

        $curl = new CurlResult($connection);

        //Get only text responses
        $curl->onHeader(function ($name, $value, $data) {
            if ($name === 'content-type') {
                $data->isBinary = !preg_match('/(text|html|json)/', strtolower($value));
            }
        });

        $curl->onBody(function ($string, stdClass $data) {
            return empty($data->isBinary);
        });

        curl_exec($connection);

        $result = $curl->getResult();

        curl_close($connection);

        return $this->responses[] = new Response(
            $url,
            Url::create($result['url']),
            $result['statusCode'],
            $result['contentType'],
            $result['content'],
            $result['headers'],
            $result['info']
        );
    }
470451
public function request($url, $method = 'GET', $headers = [], $body = null, $options = [])
    {
        if (false === is_array($options)) {
            $options = [];
        }

        $request = $this->getGuzzleClient()->createRequest($method, $url, $options);

        $request->addHeaders($headers);
        $request->setBody($body);

        $response = $this->getGuzzleClient()->send($request);

        return [
            'code'    => $response->getStatusCode(),
            'headers' => $response->getHeaders(),
            'body'    => (string)$response->getBody(),
        ];
    }
361103
private function _curl($url, $data = '', $method = 'get')
    {
        $parStr = '';
        if (is_array($data)) {
            $parStr = http_build_query($data);
        } else {
            $parStr = $data;
        }

        if (strtolower($method) == 'get') {
            $json = file_get_contents(rtrim($url, '?').'?'.$parStr);
        } else {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $parStr);
            $json = curl_exec($ch);
            curl_close($ch);
        }

        $result = json_decode($json, true);

        if (isset($result['errcode']) and $result['errcode'] != 0) {
            $this->_log("Error-{$method}-{$url}", $json, $data);
            return false;
        }

        return $result;
    }
883865
protected function _doRequest($method, $uri, $options)
    {
        return $this->httpClient->request($method, $uri, $options);
    }
1271332
protected function httpRequest($method, $uri, array $options = [])
    {
        if (null !== $this->proxy) {
            $options[RequestOptions::PROXY] = $this->proxy;
        }

        if (!isset($options[RequestOptions::HEADERS])) {
            $options[RequestOptions::HEADERS] = $this->getHttpHeaders();
        } else {
            $options[RequestOptions::HEADERS] = array_merge($this->getHttpHeaders(), $options[RequestOptions::HEADERS]);
        }

        if (!isset($options[RequestOptions::HTTP_ERRORS])) {
            $options[RequestOptions::HTTP_ERRORS] = false;
        }

        if (!isset($options[RequestOptions::ALLOW_REDIRECTS])) {
            $options[RequestOptions::ALLOW_REDIRECTS] = false;
        }

        if (!isset($options[RequestOptions::TIMEOUT]) && null !== $this->timeout) {
            $options[RequestOptions::TIMEOUT] = $this->timeout;
        }

        if (null !== $this->qps && null !== $this->lastRequestTime) {
            $lastInterval = floor((microtime(true) - $this->lastRequestTime) * 1000000);
            $timeout = ceil(1000000 / $this->qps);
            if ($lastInterval < $timeout) {
                usleep($timeout - $lastInterval);
            }
        }

        $response = $this->getHttpClient()->request($method, $uri, $options);
        $this->lastRequestTime = microtime(true);
        $this->history[] = [
            'method' => $method,
            'uri' => $uri,
            'time' => $this->lastRequestTime,
            'status' => $response->getStatusCode(),
        ];

        return $response;
    }
918504
static public function json(
        $url,
        $parameterList = '',
        $method = self::HTTP_METHOD_GET,
        array $headerList = [],
        $associative = false,
        array $optionList = [],
        $retries = 5
    ) {
        $headerList[] = static::CONTENT_TYPE;

        $defaultOptionList = [
            CURLOPT_HEADER => false,
            CURLOPT_HTTPHEADER => $headerList,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_NOSIGNAL => true,
            CURLOPT_CONNECTTIMEOUT_MS => 30 * 1000,
            CURLOPT_TIMEOUT_MS => 600 * 1000,
        ];

        switch ($method) {
            case self::HTTP_METHOD_GET:
                $parameterList = (array) $parameterList;
                $parameters = '';
                foreach ($parameterList as $key => $value) {
                    if (is_array($value)) {
                        $parameters .= (empty($parameters) ? '' : '&') . self::normalizeArrayValues($key, $value);

                        unset($parameterList[$key]);
                    }
                }

                if (count($parameterList) > 0) {
                    $parameters .= (empty($parameters) ? '' : '&') . http_build_query($parameterList);
                }

                if ($parameters) {
                    $url .= '?' . $parameters;
                }
                break;
            case self::HTTP_METHOD_POST:
                $optionList[CURLOPT_POST] = true;
                $optionList[CURLOPT_POSTFIELDS] = $parameterList;
                break;
        }

        $optionList[CURLOPT_URL] = $url;

        $curl = curl_init();

        curl_setopt_array($curl, $optionList + $defaultOptionList);

        $tries = 0;
        $triesData = [];

        do {
            $timeStart = microtime(true);
            $response = curl_exec($curl);
            $executionTime = microtime(true) - $timeStart;
            $information = curl_getinfo($curl);
            $errorCode = curl_errno($curl);
            $error = curl_error($curl);

            if ($errorCode) {
                $triesData[$tries] = [
                    'errorCode' => $errorCode,
                    'error' => $error,
                    'response' => $response,
                    'information' => $information,
                ];
            }

            $tries++;
        } while (in_array($errorCode, self::$retryErrorList) && $tries < $retries);

        if ($errorCode) {
            throw new CurlErrorException(
                'Curl error: ' . $error,
                StatusCode::INTERNAL_SERVER_ERROR,
                [
                    'errorCode' => $errorCode,
                    'error' => $error,
                    'executionTime' => $executionTime,
                    'tries' => $tries,
                    'triesData' => $triesData,
                    'optionList' => $optionList,
                    'response' => $response,
                    'information' => $information,
                ]
            );
        }

        if (!empty($information['http_code']) && $information['http_code'] >= StatusCode::BAD_REQUEST) {
            throw new HttpErrorException(
                'Http error: ' . $response,
                StatusCode::INTERNAL_SERVER_ERROR,
                [
                    'executionTime' => $executionTime,
                    'tries' => $tries,
                    'triesData' => $triesData,
                    'optionList' => $optionList,
                    'response' => $response,
                    'information' => $information,
                ]
            );
        }

        $data = json_decode($response, $associative);
        $jsonErrorCode = json_last_error();

        if (JSON_ERROR_NONE !== $jsonErrorCode) {
            throw new JsonErrorException(
                'Json error: (' . $jsonErrorCode . ')' . json_last_error_msg(),
                StatusCode::INTERNAL_SERVER_ERROR,
                [
                    'errorCode' => json_last_error(),
                    'error' => json_last_error_msg(),
                    'executionTime' => $executionTime,
                    'tries' => $tries,
                    'triesData' => $triesData,
                    'optionList' => $optionList,
                    'response' => $response,
                    'information' => $information,
                ]
            );
        }

        $data['curl'] = [
            'executionTime' => $executionTime,
            'tries' => $tries,
            'triesData' => $triesData,
            'optionList' => $optionList,
            'information' => $information,
        ];

        return $data;
    }