mirror of
https://github.com/codeigniter4/CodeIgniter4.git
synced 2025-02-20 11:44:28 +08:00
Adding some options and standard abilities to CURLRequest. More to come...
This commit is contained in:
parent
efda966e14
commit
ba2ab15f02
@ -14,23 +14,21 @@ use App\Config\AppConfig;
|
|||||||
*/
|
*/
|
||||||
class CURLRequest extends Request
|
class CURLRequest extends Request
|
||||||
{
|
{
|
||||||
protected $timeout = 2.0;
|
/**
|
||||||
|
* @var ResponseInterface
|
||||||
|
*/
|
||||||
protected $response;
|
protected $response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The first poriton of URI that is prepended
|
* @var URI
|
||||||
* to all relative requests.
|
|
||||||
* @var string
|
|
||||||
*/
|
*/
|
||||||
protected $base_uri;
|
protected $base_uri;
|
||||||
|
|
||||||
/**
|
protected $config = [
|
||||||
* If TRUE, turns on VERBOSE reporting through cURL
|
'timeout' => 0.0,
|
||||||
* and output to STDOUT
|
'connect_timeout' => 150,
|
||||||
* @var bool
|
'debug' => false
|
||||||
*/
|
];
|
||||||
protected $debug = false;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
@ -76,7 +74,7 @@ class CURLRequest extends Request
|
|||||||
|
|
||||||
$url = $this->prepareURL($url);
|
$url = $this->prepareURL($url);
|
||||||
|
|
||||||
$this->send($url);
|
$this->send($method, $url);
|
||||||
|
|
||||||
return $this->response;
|
return $this->response;
|
||||||
}
|
}
|
||||||
@ -202,12 +200,19 @@ class CURLRequest extends Request
|
|||||||
unset($options['base_uri']);
|
unset($options['base_uri']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('headers', $options) && is_array($options['headers']))
|
||||||
|
{
|
||||||
|
foreach ($options['headers'] as $name => $value)
|
||||||
|
{
|
||||||
|
$this->setHeader($name, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($options['headers']);
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($options as $key => $value)
|
foreach ($options as $key => $value)
|
||||||
{
|
{
|
||||||
if (isset($this->$key))
|
$this->config[$key] = $value;
|
||||||
{
|
|
||||||
$this->$key = $value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,7 +246,7 @@ class CURLRequest extends Request
|
|||||||
*
|
*
|
||||||
* @param string $url
|
* @param string $url
|
||||||
*/
|
*/
|
||||||
public function send(string $url)
|
public function send(string $method, string $url)
|
||||||
{
|
{
|
||||||
$ch = curl_init();
|
$ch = curl_init();
|
||||||
|
|
||||||
@ -251,15 +256,12 @@ class CURLRequest extends Request
|
|||||||
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
|
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
|
||||||
|
|
||||||
$this->setCURLOptions($ch);
|
$this->setCURLOptions($ch);
|
||||||
|
$this->applyMethod($method, $ch);
|
||||||
|
$this->applyRequestHeaders($ch);
|
||||||
|
|
||||||
// Send the request and wait for a response.
|
// Send the request and wait for a response.
|
||||||
$output = curl_exec($ch);
|
$output = curl_exec($ch);
|
||||||
|
|
||||||
if ($this->debug)
|
|
||||||
{
|
|
||||||
echo $output;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($output === false)
|
if($output === false)
|
||||||
{
|
{
|
||||||
throw new \RuntimeException(curl_errno($ch) .': '. curl_error($ch));
|
throw new \RuntimeException(curl_errno($ch) .': '. curl_error($ch));
|
||||||
@ -281,12 +283,84 @@ class CURLRequest extends Request
|
|||||||
$body = substr($output, $break+4);
|
$body = substr($output, $break+4);
|
||||||
$this->response->setBody($body);
|
$this->response->setBody($body);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->response->setBody($output);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes all headers current part of this request and adds them
|
||||||
|
* to the cURL request.
|
||||||
|
*
|
||||||
|
* @param $handle
|
||||||
|
*/
|
||||||
|
protected function applyRequestHeaders($handle)
|
||||||
|
{
|
||||||
|
$headers = $this->headers();
|
||||||
|
|
||||||
|
if (empty($head)) return;
|
||||||
|
|
||||||
|
$set = [];
|
||||||
|
|
||||||
|
foreach ($headers as $name => $value)
|
||||||
|
{
|
||||||
|
$set[] = $name.': '. $this->headerLine($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_setopt($handle, CURLOPT_HTTPHEADER, $set);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
protected function applyMethod($method, $handle)
|
||||||
|
{
|
||||||
|
$method = strtoupper($method);
|
||||||
|
|
||||||
|
curl_setopt($handle, CURLOPT_CUSTOMREQUEST, $method);
|
||||||
|
|
||||||
|
$size = strlen($this->body);
|
||||||
|
|
||||||
|
// Have content?
|
||||||
|
if ($size === null || $size > 0)
|
||||||
|
{
|
||||||
|
$this->applyBody($handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($method == 'PUT' || $method == 'POST')
|
||||||
|
{
|
||||||
|
// See http://tools.ietf.org/html/rfc7230#section-3.3.2
|
||||||
|
if (is_null($this->header('content-length')))
|
||||||
|
{
|
||||||
|
$this->setHeader('Content-Length', 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ($method == 'HEAD')
|
||||||
|
{
|
||||||
|
curl_setopt($handle, CURLOPT_NOBODY, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
protected function applyBody($handle)
|
||||||
|
{
|
||||||
|
if (! empty($this->body))
|
||||||
|
{
|
||||||
|
curl_setopt($handle, CURLOPT_POSTFIELDS, (string)$this->body());
|
||||||
|
}
|
||||||
|
|
||||||
|
// curl sometimes adds a content type by default, prevent this
|
||||||
|
$this->setHeader('Content-Type', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the header retrieved from the cURL response into
|
* Parses the header retrieved from the cURL response into
|
||||||
* our Response object.
|
* our Response object.
|
||||||
@ -325,8 +399,68 @@ class CURLRequest extends Request
|
|||||||
|
|
||||||
protected function setCURLOptions($handle)
|
protected function setCURLOptions($handle)
|
||||||
{
|
{
|
||||||
|
// Auth Headers
|
||||||
|
if (! empty($this->config['auth']))
|
||||||
|
{
|
||||||
|
curl_setopt($handle, CURLOPT_USERPWD, $this->config['auth'][0].':'.$this->config['auth'][1]);
|
||||||
|
|
||||||
|
if (! empty($this->config['auth'][2]) && strtolower($this->config['auth'][2]) == 'digest')
|
||||||
|
{
|
||||||
|
curl_setopt($handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
curl_setopt($handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Certificate
|
||||||
|
if (! empty($this->config['cert']))
|
||||||
|
{
|
||||||
|
$cert = $this->config['cert'];
|
||||||
|
|
||||||
|
if (is_array($cert))
|
||||||
|
{
|
||||||
|
curl_setopt($handle, CURLOPT_SSLCERTPASSWD, $cert[1]);
|
||||||
|
$cert = $cert[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! file_exists($cert))
|
||||||
|
{
|
||||||
|
throw new \InvalidArgumentException('SSL certificate not found at: '. $cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_setopt($handle, CURLOPT_SSLCERT, $cert);
|
||||||
|
}
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
curl_setopt($handle, CURLOPT_VERBOSE, (bool)$this->debug);
|
if (isset($this->config['debug']))
|
||||||
|
{
|
||||||
|
curl_setopt($handle, CURLOPT_VERBOSE, 1);
|
||||||
|
curl_setopt($handle, CURLOPT_STDERR, is_bool($this->config['debug']) ? fopen('php://output', 'w+') : $this->config['debug']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode Content
|
||||||
|
if (! empty($this->config['decode_content']))
|
||||||
|
{
|
||||||
|
$accept = $this->headerLine('Accept-Encoding');
|
||||||
|
|
||||||
|
if ($accept)
|
||||||
|
{
|
||||||
|
curl_setopt($handle, CURLOPT_ENCODING, $accept);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
curl_setopt($handle, CURLOPT_ENCODING, '');
|
||||||
|
curl_setopt($handle, CURLOPT_HTTPHEADER, 'Accept-Encoding:');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timeout
|
||||||
|
curl_setopt($handle, CURLOPT_TIMEOUT_MS, (float)$this->config['timeout'] * 1000);
|
||||||
|
|
||||||
|
// Connection Timeout
|
||||||
|
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, (float)$this->config['connect_timeout'] * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
@ -90,7 +90,7 @@ Base URI
|
|||||||
|
|
||||||
A ``base_uri`` can be set as one of the options during the instantiation of the class. This allows you to
|
A ``base_uri`` can be set as one of the options during the instantiation of the class. This allows you to
|
||||||
set a base URI, and then make all requests with that client using relative URLs. This is especially handy
|
set a base URI, and then make all requests with that client using relative URLs. This is especially handy
|
||||||
when working with APIs.
|
when working with APIs.::
|
||||||
|
|
||||||
$client = Services::curlrequest([
|
$client = Services::curlrequest([
|
||||||
'base_uri' => 'https://example.com/api/v1/'
|
'base_uri' => 'https://example.com/api/v1/'
|
||||||
@ -159,3 +159,88 @@ Request Options
|
|||||||
This section describes all of the available options you may pass into the constructor, the ``request()`` method,
|
This section describes all of the available options you may pass into the constructor, the ``request()`` method,
|
||||||
or any of the shortcut methods.
|
or any of the shortcut methods.
|
||||||
|
|
||||||
|
|
||||||
|
Auth
|
||||||
|
====
|
||||||
|
|
||||||
|
Allows you to provide Authentication details for `HTTP Basic <http://www.ietf.org/rfc/rfc2069.txt>`_ and
|
||||||
|
`Digest <http://www.ietf.org/rfc/rfc2069.txt>`_ and authentication. Your script may have to do extra to support
|
||||||
|
Digest authentication - this simply passes the username and password along for you. The value must be an
|
||||||
|
array where the first element is the username, and the second is the password. The third parameter should be
|
||||||
|
the type of authentication to use, either ``basic`` or ``digest``.::
|
||||||
|
|
||||||
|
$client->request('GET', 'http://example.com', ['auth' => ['username', 'password', 'digest']]);
|
||||||
|
|
||||||
|
Body
|
||||||
|
====
|
||||||
|
|
||||||
|
There are two ways to set the body of the request for request types that support them, like PUT, OR POST.
|
||||||
|
The first way is to use the ``setBody()`` method::
|
||||||
|
|
||||||
|
$client->setBody($body)
|
||||||
|
->request('put', 'http://example.com');
|
||||||
|
|
||||||
|
The second method is by passing a ``body`` option in. This is provided to maintain Guzzle API compatibility,
|
||||||
|
and functions the exact same way as the previous example. The value must be a string.::
|
||||||
|
|
||||||
|
$client->request('put', 'http://example.com', ['body' => $body]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Certificates
|
||||||
|
============
|
||||||
|
|
||||||
|
To specify the location of a PEM formatted client-side certificate, pass a string with the full path to the
|
||||||
|
file as the ``cert`` option. If a password is required, set the value to an array with the first element
|
||||||
|
as the path to the certificate, and the second as the password::
|
||||||
|
|
||||||
|
$client->request('get', '/', ['cert' => ['/path/server.pem', 'password']);
|
||||||
|
|
||||||
|
Connection Timeout
|
||||||
|
==================
|
||||||
|
|
||||||
|
By default, CodeIgniter does not impose a limit for cURL to attempt to connect to a website. If you need to
|
||||||
|
modify this value, you can do so by passing the amount of time in seconds with the ``connect_timeout`` option.
|
||||||
|
You can pass 0 to wait indefinitely::
|
||||||
|
|
||||||
|
$response->request('GET', 'http://example.com', ['connect_timeout' => 0]);
|
||||||
|
|
||||||
|
Debug
|
||||||
|
=====
|
||||||
|
|
||||||
|
When ``debug`` is passed and set to ``true``, this will enable additional debugging to echo to STDOUT during the
|
||||||
|
script execution. This is done by passing CURLOPT_VERBOSE and echoing the output::
|
||||||
|
|
||||||
|
$response->request('GET', 'http://example.com', ['debug' => true]);
|
||||||
|
|
||||||
|
You can pass a filename as the value for debug to have the output written to a file::
|
||||||
|
|
||||||
|
$response->request('GET', 'http://example.com', ['debug' => '/usr/local/curl_log.txt']);
|
||||||
|
|
||||||
|
Headers
|
||||||
|
=======
|
||||||
|
|
||||||
|
While you can set any headers this request needs by using the ``setHeader()`` method, you can also pass an associative
|
||||||
|
array of headers in as an option. Each key is the name of a header, and each value is a string or array of strings
|
||||||
|
representing the header field values.::
|
||||||
|
|
||||||
|
$client->request('get', '/', [
|
||||||
|
'headers' => [
|
||||||
|
'User-Agent' => 'testing/1.0',
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
'X-Foo' => ['Bar', 'Baz']
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
If headers are passed into the constructor they are treated as default values that will be overridden later by any
|
||||||
|
further headers arrays or calls to ``setHeader()``.
|
||||||
|
|
||||||
|
Timeout
|
||||||
|
=======
|
||||||
|
|
||||||
|
By default, cURL functions are allowed to run as long as they take, with no time limit. You can modify this with the ``timeout``
|
||||||
|
option. The value should be the number of seconds you want the functions to execute for. Use 0 to wait indefinitely::
|
||||||
|
|
||||||
|
$response->request('GET', 'http://example.com', ['timeout' => 5]);
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user