123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516 |
- <?php
- namespace App\Models;
- use RuntimeException;
- class Curl
- {
- const METHOD_GET = 'GET';
- const METHOD_POST = 'POST';
- const METHOD_DELETE = 'DELETE';
- const METHOD_PATCH = 'PATCH';
- const METHOD_PUT = 'PUT';
- const METHOD_OPTIONS = 'OPTIONS';
- /**
- * @var string The HTTP address to use.
- */
- public $url;
- /**
- * @var string The method the request should use.
- */
- public $method;
- /**
- * @var array The headers to be sent with the request.
- */
- public $headers = [];
- /**
- * @var string The last response body.
- */
- public $body = '';
- /**
- * @var string The last response body (without headers extracted).
- */
- public $rawBody = '';
- /**
- * @var array The last returned HTTP code.
- */
- public $code;
- /**
- * @var array The cURL response information.
- */
- public $info;
- /**
- * @var array cURL Options.
- */
- public $requestOptions;
- /**
- * @var array Request data.
- */
- public $requestData;
- /**
- * @var array Request headers.
- */
- public $requestHeaders;
- /**
- * @var string Argument separator.
- */
- public $argumentSeparator = '&';
- /**
- * @var string If writing response to a file, which file to use.
- */
- public $streamFile;
- /**
- * @var string If writing response to a file, which write filter to apply.
- */
- public $streamFilter;
- /**
- * @var int The maximum redirects allowed.
- */
- public $maxRedirects = 10;
- /**
- * @var int Internal counter
- */
- protected $redirectCount = null;
- /**
- * Make the object with common properties
- * @param string $url HTTP request address
- * @param string $method Request method (GET, POST, PUT, DELETE, etc)
- * @param callable $options Callable helper function to modify the object
- */
- public static function make($url, $method, $options = null)
- {
- $http = new self;
- $http->url = $url;
- $http->method = $method;
- if ($options && is_callable($options)) {
- $options($http);
- }
- return $http;
- }
- /**
- * Make a HTTP GET call.
- * @param string $url
- * @param callable $options
- * @return self
- */
- public static function get($url, $options = null)
- {
- $http = self::make($url, self::METHOD_GET, $options);
- return $http->send();
- }
- /**
- * Make a HTTP POST call.
- * @param string $url
- * @param callable $options
- * @return self
- */
- public static function post($url, $options = null)
- {
- $http = self::make($url, self::METHOD_POST, $options);
- return $http->send();
- }
- /**
- * Make a HTTP DELETE call.
- * @param string $url
- * @param callable $options
- * @return self
- */
- public static function delete($url, $options = null)
- {
- $http = self::make($url, self::METHOD_DELETE, $options);
- return $http->send();
- }
- /**
- * Make a HTTP PATCH call.
- * @param string $url
- * @param callable $options
- * @return self
- */
- public static function patch($url, $options = null)
- {
- $http = self::make($url, self::METHOD_PATCH, $options);
- return $http->send();
- }
- /**
- * Make a HTTP PUT call.
- * @param string $url
- * @param callable $options
- * @return self
- */
- public static function put($url, $options = null)
- {
- $http = self::make($url, self::METHOD_PUT, $options);
- return $http->send();
- }
- /**
- * Make a HTTP OPTIONS call.
- * @param string $url
- * @param callable $options
- * @return self
- */
- public static function options($url, $options = null)
- {
- $http = self::make($url, self::METHOD_OPTIONS, $options);
- return $http->send();
- }
- /**
- * Execute the HTTP request.
- * @return string response body
- */
- public function send()
- {
- if (!function_exists('curl_init')) {
- echo 'cURL PHP extension required.'.PHP_EOL;
- exit(1);
- }
- /*
- * Create and execute the cURL Resource
- */
- $curl = curl_init();
- curl_setopt($curl, CURLOPT_URL, $this->url);
- curl_setopt($curl, CURLOPT_HEADER, true);
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
- curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
- if (defined('CURLOPT_FOLLOWLOCATION') && !ini_get('open_basedir')) {
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
- curl_setopt($curl, CURLOPT_MAXREDIRS, $this->maxRedirects);
- }
- if ($this->requestOptions && is_array($this->requestOptions)) {
- curl_setopt_array($curl, $this->requestOptions);
- }
- /*
- * Set request method
- */
- if ($this->method == self::METHOD_POST) {
- curl_setopt($curl, CURLOPT_POST, true);
- }
- elseif ($this->method !== self::METHOD_GET) {
- curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->method);
- }
- /*
- * Set request data
- */
- if ($this->requestData) {
- if (in_array($this->method, [self::METHOD_POST, self::METHOD_PATCH, self::METHOD_PUT])) {
- curl_setopt($curl, CURLOPT_POSTFIELDS, $this->getRequestData());
- }
- elseif ($this->method == self::METHOD_GET) {
- curl_setopt($curl, CURLOPT_URL, $this->url . '?' . $this->getRequestData());
- }
- }
- /*
- * Set request headers
- */
- if ($this->requestHeaders) {
- $requestHeaders = [];
- foreach ($this->requestHeaders as $key => $value) {
- $requestHeaders[] = $key . ': ' . $value;
- }
- curl_setopt($curl, CURLOPT_HTTPHEADER, $requestHeaders);
- }
- /*
- * Handle output to file
- */
- if ($this->streamFile) {
- $stream = fopen($this->streamFile, 'w');
- if ($this->streamFilter) {
- stream_filter_append($stream, $this->streamFilter, STREAM_FILTER_WRITE);
- }
- curl_setopt($curl, CURLOPT_HEADER, false);
- curl_setopt($curl, CURLOPT_FILE, $stream);
- curl_exec($curl);
- }
- /*
- * Handle output to variable
- */
- else {
- $response = $this->rawBody = curl_exec($curl);
- $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
- $this->headers = $this->headerToArray(substr($response, 0, $headerSize));
- $this->body = substr($response, $headerSize);
- }
- $this->info = curl_getinfo($curl);
- $this->code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
- /*
- * Close resources
- */
- curl_close($curl);
- if ($this->streamFile) {
- fclose($stream);
- }
- /*
- * Emulate FOLLOW LOCATION behavior
- */
- if (!defined('CURLOPT_FOLLOWLOCATION') || ini_get('open_basedir')) {
- if ($this->redirectCount === null) {
- $this->redirectCount = $this->maxRedirects;
- }
- if (in_array($this->code, [301, 302])) {
- $this->url = array_get($this->info, 'url');
- if (!empty($this->url) && $this->redirectCount > 0) {
- $this->redirectCount -= 1;
- return $this->send();
- }
- }
- }
- return $this;
- }
- /**
- * Return the request data set.
- * @return string
- */
- public function getRequestData()
- {
- if (
- $this->method !== self::METHOD_GET
- && isset($this->requestOptions[CURLOPT_POSTFIELDS])
- && empty($this->requestData)
- ) {
- return $this->requestOptions[CURLOPT_POSTFIELDS];
- }
- if (!empty($this->requestData)) {
- return http_build_query($this->requestData, '', $this->argumentSeparator);
- }
- return '';
- }
- /**
- * Turn a header string into an array.
- * @param string $header
- * @return array
- */
- protected function headerToArray($header)
- {
- $headers = [];
- $parts = explode("\r\n", $header);
- foreach ($parts as $singleHeader) {
- $delimiter = strpos($singleHeader, ': ');
- if ($delimiter !== false) {
- $key = substr($singleHeader, 0, $delimiter);
- $val = substr($singleHeader, $delimiter + 2);
- $headers[$key] = $val;
- }
- else {
- $delimiter = strpos($singleHeader, ' ');
- if ($delimiter !== false) {
- $key = substr($singleHeader, 0, $delimiter);
- $val = substr($singleHeader, $delimiter + 1);
- $headers[$key] = $val;
- }
- }
- }
- return $headers;
- }
- /**
- * Add a data to the request.
- * @param string $value
- * @return self
- */
- public function data($key, $value = null)
- {
- if (is_array($key)) {
- foreach ($key as $_key => $_value) {
- $this->data($_key, $_value);
- }
- return $this;
- }
- $this->requestData[$key] = $value;
- return $this;
- }
- /**
- * Add a header to the request.
- * @param string $value
- * @return self
- */
- public function header($key, $value = null)
- {
- if (is_array($key)) {
- foreach ($key as $_key => $_value) {
- $this->header($_key, $_value);
- }
- return $this;
- }
- $this->requestHeaders[$key] = $value;
- return $this;
- }
- /**
- * Sets a proxy to use with this request
- */
- public function proxy($type, $host, $port, $username = null, $password = null)
- {
- if ($type === 'http') {
- $this->setOption(CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
- }
- elseif ($type === 'socks4') {
- $this->setOption(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
- }
- elseif ($type === 'socks5') {
- $this->setOption(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
- }
- $this->setOption(CURLOPT_PROXY, $host . ':' . $port);
- if ($username && $password) {
- $this->setOption(CURLOPT_PROXYUSERPWD, $username . ':' . $password);
- }
- return $this;
- }
- /**
- * Adds authentication to the comms.
- * @param string $user
- * @param string $pass
- * @return self
- */
- public function auth($user, $pass = null)
- {
- if (strpos($user, ':') !== false && !$pass) {
- list($user, $pass) = explode(':', $user);
- }
- $this->setOption(CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
- $this->setOption(CURLOPT_USERPWD, $user . ':' . $pass);
- return $this;
- }
- /**
- * Disable follow location (redirects)
- */
- public function noRedirect()
- {
- $this->setOption(CURLOPT_FOLLOWLOCATION, false);
- return $this;
- }
- /**
- * Enable SSL verification
- */
- public function verifySSL()
- {
- $this->setOption(CURLOPT_SSL_VERIFYPEER, true);
- $this->setOption(CURLOPT_SSL_VERIFYHOST, true);
- return $this;
- }
- /**
- * Sets the request timeout.
- * @param string $timeout
- * @return self
- */
- public function timeout($timeout)
- {
- $this->setOption(CURLOPT_CONNECTTIMEOUT, $timeout);
- $this->setOption(CURLOPT_TIMEOUT, $timeout);
- return $this;
- }
- /**
- * Write the response to a file
- * @param string $path Path to file
- * @param string $filter Stream filter as listed in stream_get_filters()
- * @return self
- */
- public function toFile($path, $filter = null)
- {
- $this->streamFile = $path;
- if ($filter) {
- $this->streamFilter = $filter;
- }
- return $this;
- }
- /**
- * Add a single option to the request.
- * @param string $option
- * @param string $value
- * @return self
- */
- public function setOption($option, $value = null)
- {
- if (is_array($option)) {
- foreach ($option as $_option => $_value) {
- $this->setOption($_option, $_value);
- }
- return $this;
- }
- if (is_string($option) && defined($option)) {
- $optionKey = constant($option);
- $this->requestOptions[$optionKey] = $value;
- } elseif (is_int($option)) {
- $constants = get_defined_constants(true);
- $curlOptConstants = array_flip(array_filter($constants['curl'], function ($key) {
- return strpos($key, 'CURLOPT_') === 0;
- }, ARRAY_FILTER_USE_KEY));
- if (isset($curlOptConstants[$option])) {
- $this->requestOptions[$option] = $value;
- } else {
- throw new RuntimeException('$option parameter must be a CURLOPT constant or equivalent integer');
- }
- } else {
- throw new RuntimeException('$option parameter must be a CURLOPT constant or equivalent integer');
- }
- return $this;
- }
- /**
- * Handy if this object is called directly.
- * @return string The last response.
- */
- public function __toString()
- {
- return (string) $this->body;
- }
- }
|