mirror of
https://github.com/codeigniter4/CodeIgniter4.git
synced 2025-02-20 11:44:28 +08:00
Added the allow_redirects option to CURLRequest.
This commit is contained in:
parent
1bb77d51ba
commit
869fb76dbc
@ -26,12 +26,25 @@ class CURLRequest extends Request
|
||||
|
||||
/**
|
||||
* The setting values
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $config = [
|
||||
'timeout' => 0.0,
|
||||
'connect_timeout' => 150,
|
||||
'debug' => false
|
||||
'timeout' => 0.0,
|
||||
'connect_timeout' => 150,
|
||||
'debug' => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* Default values for when 'allow_redirects'
|
||||
* option is true.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $redirectDefaults = [
|
||||
'max' => 5,
|
||||
'strict' => true,
|
||||
'protocols' => ['http', 'https'],
|
||||
];
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
@ -45,9 +58,9 @@ class CURLRequest extends Request
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(AppConfig $config, URI $uri, ResponseInterface $response=null, array $options=[])
|
||||
public function __construct(AppConfig $config, URI $uri, ResponseInterface $response = null, array $options = [])
|
||||
{
|
||||
if (! function_exists('curl_version'))
|
||||
if ( ! function_exists('curl_version'))
|
||||
{
|
||||
throw new \RuntimeException('CURL must be enabled to use the CURLRequest class.');
|
||||
}
|
||||
@ -258,13 +271,12 @@ class CURLRequest extends Request
|
||||
public function method($upper = false): string
|
||||
{
|
||||
return ($upper)
|
||||
? strtoupper($this->method)
|
||||
: strtolower($this->method);
|
||||
? strtoupper($this->method)
|
||||
: strtolower($this->method);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* Fires the actual cURL request.
|
||||
*
|
||||
@ -275,10 +287,10 @@ class CURLRequest extends Request
|
||||
// Reset our curl options so we're on a fresh slate.
|
||||
$curl_options = [];
|
||||
|
||||
$curl_options[CURLOPT_URL] = $url;
|
||||
$curl_options[CURLOPT_URL] = $url;
|
||||
$curl_options[CURLOPT_RETURNTRANSFER] = true;
|
||||
$curl_options[CURLOPT_HEADER] = true;
|
||||
$curl_options[CURLOPT_FRESH_CONNECT] = true;
|
||||
$curl_options[CURLOPT_HEADER] = true;
|
||||
$curl_options[CURLOPT_FRESH_CONNECT] = true;
|
||||
|
||||
$curl_options = $this->setCURLOptions($curl_options, $this->config);
|
||||
$curl_options = $this->applyMethod($method, $curl_options);
|
||||
@ -297,7 +309,7 @@ class CURLRequest extends Request
|
||||
$this->setResponseHeaders($headers);
|
||||
|
||||
// Our body
|
||||
$body = substr($output, $break+4);
|
||||
$body = substr($output, $break + 4);
|
||||
$this->response->setBody($body);
|
||||
}
|
||||
else
|
||||
@ -316,17 +328,20 @@ class CURLRequest extends Request
|
||||
*
|
||||
* @param array $curl_options
|
||||
*/
|
||||
protected function applyRequestHeaders(array $curl_options=[]): array
|
||||
protected function applyRequestHeaders(array $curl_options = []): array
|
||||
{
|
||||
$headers = $this->headers();
|
||||
$headers = $this->headers();
|
||||
|
||||
if (empty($head)) return $curl_options;
|
||||
if (empty($head))
|
||||
{
|
||||
return $curl_options;
|
||||
}
|
||||
|
||||
$set = [];
|
||||
|
||||
foreach ($headers as $name => $value)
|
||||
{
|
||||
$set[] = $name.': '. $this->headerLine($name);
|
||||
$set[] = $name.': '.$this->headerLine($name);
|
||||
}
|
||||
|
||||
$curl_options[CURLOPT_HTTPHEADER] = $set;
|
||||
@ -340,7 +355,7 @@ class CURLRequest extends Request
|
||||
{
|
||||
$method = strtoupper($method);
|
||||
|
||||
$this->method = $method;
|
||||
$this->method = $method;
|
||||
$curl_options[CURLOPT_CUSTOMREQUEST] = $method;
|
||||
|
||||
$size = strlen($this->body);
|
||||
@ -349,6 +364,7 @@ class CURLRequest extends Request
|
||||
if ($size === null || $size > 0)
|
||||
{
|
||||
$curl_options = $this->applyBody($curl_options);
|
||||
|
||||
return $curl_options;
|
||||
}
|
||||
|
||||
@ -370,9 +386,9 @@ class CURLRequest extends Request
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
protected function applyBody(array $curl_options=[]): array
|
||||
protected function applyBody(array $curl_options = []): array
|
||||
{
|
||||
if (! empty($this->body))
|
||||
if ( ! empty($this->body))
|
||||
{
|
||||
$curl_options[CURLOPT_POSTFIELDS] = (string)$this->body();
|
||||
}
|
||||
@ -398,7 +414,7 @@ class CURLRequest extends Request
|
||||
if (($pos = strpos($header, ':')) !== false)
|
||||
{
|
||||
$title = substr($header, 0, $pos);
|
||||
$value = substr($header, $pos+1);
|
||||
$value = substr($header, $pos + 1);
|
||||
|
||||
$this->response->setHeader($title, $value);
|
||||
}
|
||||
@ -421,14 +437,14 @@ class CURLRequest extends Request
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
protected function setCURLOptions(array $curl_options=[], array $config=[])
|
||||
protected function setCURLOptions(array $curl_options = [], array $config = [])
|
||||
{
|
||||
// Auth Headers
|
||||
if (! empty($config['auth']))
|
||||
if ( ! empty($config['auth']))
|
||||
{
|
||||
$curl_options[CURLOPT_USERPWD] = $config['auth'][0].':'.$config['auth'][1];
|
||||
|
||||
if (! empty($config['auth'][2]) && strtolower($config['auth'][2]) == 'digest')
|
||||
if ( ! empty($config['auth'][2]) && strtolower($config['auth'][2]) == 'digest')
|
||||
{
|
||||
$curl_options[CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST;
|
||||
}
|
||||
@ -439,19 +455,19 @@ class CURLRequest extends Request
|
||||
}
|
||||
|
||||
// Certificate
|
||||
if (! empty($config['cert']))
|
||||
if ( ! empty($config['cert']))
|
||||
{
|
||||
$cert = $config['cert'];
|
||||
|
||||
if (is_array($cert))
|
||||
{
|
||||
$curl_options[CURLOPT_SSLCERTPASSWD] = $cert[1];
|
||||
$cert = $cert[0];
|
||||
$cert = $cert[0];
|
||||
}
|
||||
|
||||
if (! file_exists($cert))
|
||||
if ( ! file_exists($cert))
|
||||
{
|
||||
throw new \InvalidArgumentException('SSL certificate not found at: '. $cert);
|
||||
throw new \InvalidArgumentException('SSL certificate not found at: '.$cert);
|
||||
}
|
||||
|
||||
$curl_options[CURLOPT_SSLCERT] = $cert;
|
||||
@ -461,11 +477,11 @@ class CURLRequest extends Request
|
||||
if (isset($config['debug']))
|
||||
{
|
||||
$curl_options[CURLOPT_VERBOSE] = 1;
|
||||
$curl_options[CURLOPT_STDERR] = is_bool($config['debug']) ? fopen('php://output', 'w+') : $config['debug'];
|
||||
$curl_options[CURLOPT_STDERR] = is_bool($config['debug']) ? fopen('php://output', 'w+') : $config['debug'];
|
||||
}
|
||||
|
||||
// Decode Content
|
||||
if (! empty($config['decode_content']))
|
||||
if ( ! empty($config['decode_content']))
|
||||
{
|
||||
$accept = $this->headerLine('Accept-Encoding');
|
||||
|
||||
@ -475,11 +491,45 @@ class CURLRequest extends Request
|
||||
}
|
||||
else
|
||||
{
|
||||
$curl_options[CURLOPT_ENCODING] = '';
|
||||
$curl_options[CURLOPT_ENCODING] = '';
|
||||
$curl_options[CURLOPT_HTTPHEADER] = 'Accept-Encoding';
|
||||
}
|
||||
}
|
||||
|
||||
// Allow Redirects
|
||||
if (array_key_exists('allow_redirects', $config))
|
||||
{
|
||||
$settings = $this->redirectDefaults;
|
||||
|
||||
if (is_array($config['allow_redirects']))
|
||||
{
|
||||
$settings = array_merge($settings, $config['allow_redirects']);
|
||||
}
|
||||
|
||||
if ($config['allow_redirects'] === false)
|
||||
{
|
||||
$curl_options[CURLOPT_FOLLOWLOCATION] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$curl_options[CURLOPT_FOLLOWLOCATION] = 1;
|
||||
$curl_options[CURLOPT_MAXREDIRS] = $settings['max'];
|
||||
|
||||
if ($settings['strict'] == true)
|
||||
{
|
||||
$curl_options[CURLOPT_POSTREDIR] = 1|2|4;
|
||||
}
|
||||
|
||||
$protocols = 0;
|
||||
foreach ($settings['protocols'] as $proto)
|
||||
{
|
||||
$protocols += constant('CURLPROTO_'.strtoupper($proto));
|
||||
}
|
||||
|
||||
$curl_options[CURLOPT_REDIR_PROTOCOLS] = $protocols;
|
||||
}
|
||||
}
|
||||
|
||||
// Timeout
|
||||
$curl_options[CURLOPT_TIMEOUT_MS] = (float)$config['timeout'] * 1000;
|
||||
|
||||
@ -508,9 +558,9 @@ class CURLRequest extends Request
|
||||
// Send the request and wait for a response.
|
||||
$output = curl_exec($ch);
|
||||
|
||||
if($output === false)
|
||||
if ($output === false)
|
||||
{
|
||||
throw new \RuntimeException(curl_errno($ch) .': '. curl_error($ch));
|
||||
throw new \RuntimeException(curl_errno($ch).': '.curl_error($ch));
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
|
@ -322,4 +322,56 @@ class CURLRequestTest extends PHPUnit_Framework_TestCase
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
public function testAllowRedirectsOptionFalse()
|
||||
{
|
||||
$response = $this->request->request('get', 'http://example.com', [
|
||||
'allow_redirects' => false
|
||||
]);
|
||||
|
||||
$options = $this->request->curl_options;
|
||||
|
||||
$this->assertTrue(isset($options[CURLOPT_FOLLOWLOCATION]));
|
||||
$this->assertEquals(0, $options[CURLOPT_FOLLOWLOCATION]);
|
||||
|
||||
$this->assertFalse(isset($options[CURLOPT_MAXREDIRS]));
|
||||
$this->assertFalse(isset($options[CURLOPT_REDIR_PROTOCOLS]));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
public function testAllowRedirectsOptionTrue()
|
||||
{
|
||||
$response = $this->request->request('get', 'http://example.com', [
|
||||
'allow_redirects' => true
|
||||
]);
|
||||
|
||||
$options = $this->request->curl_options;
|
||||
|
||||
$this->assertTrue(isset($options[CURLOPT_FOLLOWLOCATION]));
|
||||
$this->assertEquals(1, $options[CURLOPT_FOLLOWLOCATION]);
|
||||
|
||||
$this->assertTrue(isset($options[CURLOPT_MAXREDIRS]));
|
||||
$this->assertEquals(5, $options[CURLOPT_MAXREDIRS]);
|
||||
$this->assertTrue(isset($options[CURLOPT_REDIR_PROTOCOLS]));
|
||||
$this->assertEquals(CURLPROTO_HTTP|CURLPROTO_HTTPS, $options[CURLOPT_REDIR_PROTOCOLS]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
public function testAllowRedirectsOptionDefaults()
|
||||
{
|
||||
$response = $this->request->request('get', 'http://example.com', [
|
||||
'allow_redirects' => true
|
||||
]);
|
||||
|
||||
$options = $this->request->curl_options;
|
||||
|
||||
$this->assertTrue(isset($options[CURLOPT_FOLLOWLOCATION]));
|
||||
$this->assertEquals(1, $options[CURLOPT_FOLLOWLOCATION]);
|
||||
|
||||
$this->assertTrue(isset($options[CURLOPT_MAXREDIRS]));
|
||||
$this->assertTrue(isset($options[CURLOPT_REDIR_PROTOCOLS]));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
}
|
@ -159,8 +159,34 @@ Request Options
|
||||
This section describes all of the available options you may pass into the constructor, the ``request()`` method,
|
||||
or any of the shortcut methods.
|
||||
|
||||
allow_redirects
|
||||
===============
|
||||
|
||||
Auth
|
||||
By default, cURL will follow all "Location:" headers the remote servers send back. The ``allow_redirects`` option
|
||||
allows you to modify how that works.
|
||||
|
||||
If you set the value to ``false``, then it will not follow any redirects at all::
|
||||
|
||||
$client->request('GET', 'http://example.com', ['allow_redirects' => false]);
|
||||
|
||||
Setting it to ``true`` will apply the default settings to the request::
|
||||
|
||||
$client->request('GET', 'http://example.com', ['allow_redirects' => true]);
|
||||
|
||||
// Sets the following defaults:
|
||||
'max' => 5, // Maximum number of redirects to follow before stopping
|
||||
'strict' => true, // Ensure POST requests stay POST requests through redirects
|
||||
'protocols' => ['http', 'https'] // Restrict redirects to one or more protocols
|
||||
|
||||
You can pass in array as the value of the ``allow_redirects`` option to specify new settings in place of the defaults::
|
||||
|
||||
$client->request('GET', 'http://example.com', ['allow_redirects' => [
|
||||
'max' => 10,
|
||||
'protocols => ['https'] // Force HTTPS domains only.
|
||||
]]);
|
||||
|
||||
.. :note:: Following redirects does not work when PHP is in safe_mode or open_basedir is enabled.
|
||||
auth
|
||||
====
|
||||
|
||||
Allows you to provide Authentication details for `HTTP Basic <http://www.ietf.org/rfc/rfc2069.txt>`_ and
|
||||
@ -171,7 +197,7 @@ the type of authentication to use, either ``basic`` or ``digest``.::
|
||||
|
||||
$client->request('GET', 'http://example.com', ['auth' => ['username', 'password', 'digest']]);
|
||||
|
||||
Body
|
||||
body
|
||||
====
|
||||
|
||||
There are two ways to set the body of the request for request types that support them, like PUT, OR POST.
|
||||
@ -187,8 +213,8 @@ and functions the exact same way as the previous example. The value must be a st
|
||||
|
||||
|
||||
|
||||
Certificates
|
||||
============
|
||||
cert
|
||||
====
|
||||
|
||||
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
|
||||
@ -196,8 +222,8 @@ file as the ``cert`` option. If a password is required, set the value to an arra
|
||||
|
||||
$client->request('get', '/', ['cert' => ['/path/server.pem', 'password']);
|
||||
|
||||
Connection Timeout
|
||||
==================
|
||||
Connect_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.
|
||||
@ -205,7 +231,7 @@ You can pass 0 to wait indefinitely::
|
||||
|
||||
$response->request('GET', 'http://example.com', ['connect_timeout' => 0]);
|
||||
|
||||
Debug
|
||||
debug
|
||||
=====
|
||||
|
||||
When ``debug`` is passed and set to ``true``, this will enable additional debugging to echo to STDOUT during the
|
||||
@ -217,7 +243,7 @@ You can pass a filename as the value for debug to have the output written to a f
|
||||
|
||||
$response->request('GET', 'http://example.com', ['debug' => '/usr/local/curl_log.txt']);
|
||||
|
||||
Headers
|
||||
headers
|
||||
=======
|
||||
|
||||
While you can set any headers this request needs by using the ``setHeader()`` method, you can also pass an associative
|
||||
@ -235,7 +261,7 @@ representing the header field values.::
|
||||
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
|
||||
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``
|
||||
|
Loading…
x
Reference in New Issue
Block a user