Skip to content

Commit 869fb76

Browse files
committed
Added the allow_redirects option to CURLRequest.
1 parent 1bb77d5 commit 869fb76

File tree

3 files changed

+140
-12
lines changed

3 files changed

+140
-12
lines changed

system/HTTP/CURLRequest.php

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,25 @@ class CURLRequest extends Request
2626

2727
/**
2828
* The setting values
29+
*
2930
* @var array
3031
*/
3132
protected $config = [
3233
'timeout' => 0.0,
3334
'connect_timeout' => 150,
34-
'debug' => false
35+
'debug' => false,
36+
];
37+
38+
/**
39+
* Default values for when 'allow_redirects'
40+
* option is true.
41+
*
42+
* @var array
43+
*/
44+
protected $redirectDefaults = [
45+
'max' => 5,
46+
'strict' => true,
47+
'protocols' => ['http', 'https'],
3548
];
3649

3750
//--------------------------------------------------------------------
@@ -264,7 +277,6 @@ public function method($upper = false): string
264277

265278
//--------------------------------------------------------------------
266279

267-
268280
/**
269281
* Fires the actual cURL request.
270282
*
@@ -320,7 +332,10 @@ protected function applyRequestHeaders(array $curl_options=[]): array
320332
{
321333
$headers = $this->headers();
322334

323-
if (empty($head)) return $curl_options;
335+
if (empty($head))
336+
{
337+
return $curl_options;
338+
}
324339

325340
$set = [];
326341

@@ -349,6 +364,7 @@ protected function applyMethod($method, array $curl_options): array
349364
if ($size === null || $size > 0)
350365
{
351366
$curl_options = $this->applyBody($curl_options);
367+
352368
return $curl_options;
353369
}
354370

@@ -480,6 +496,40 @@ protected function setCURLOptions(array $curl_options=[], array $config=[])
480496
}
481497
}
482498

499+
// Allow Redirects
500+
if (array_key_exists('allow_redirects', $config))
501+
{
502+
$settings = $this->redirectDefaults;
503+
504+
if (is_array($config['allow_redirects']))
505+
{
506+
$settings = array_merge($settings, $config['allow_redirects']);
507+
}
508+
509+
if ($config['allow_redirects'] === false)
510+
{
511+
$curl_options[CURLOPT_FOLLOWLOCATION] = 0;
512+
}
513+
else
514+
{
515+
$curl_options[CURLOPT_FOLLOWLOCATION] = 1;
516+
$curl_options[CURLOPT_MAXREDIRS] = $settings['max'];
517+
518+
if ($settings['strict'] == true)
519+
{
520+
$curl_options[CURLOPT_POSTREDIR] = 1|2|4;
521+
}
522+
523+
$protocols = 0;
524+
foreach ($settings['protocols'] as $proto)
525+
{
526+
$protocols += constant('CURLPROTO_'.strtoupper($proto));
527+
}
528+
529+
$curl_options[CURLOPT_REDIR_PROTOCOLS] = $protocols;
530+
}
531+
}
532+
483533
// Timeout
484534
$curl_options[CURLOPT_TIMEOUT_MS] = (float)$config['timeout'] * 1000;
485535

tests/HTTP/CURLRequestTest.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,4 +322,56 @@ public function testDebugOption()
322322

323323
//--------------------------------------------------------------------
324324

325+
public function testAllowRedirectsOptionFalse()
326+
{
327+
$response = $this->request->request('get', 'http://example.com', [
328+
'allow_redirects' => false
329+
]);
330+
331+
$options = $this->request->curl_options;
332+
333+
$this->assertTrue(isset($options[CURLOPT_FOLLOWLOCATION]));
334+
$this->assertEquals(0, $options[CURLOPT_FOLLOWLOCATION]);
335+
336+
$this->assertFalse(isset($options[CURLOPT_MAXREDIRS]));
337+
$this->assertFalse(isset($options[CURLOPT_REDIR_PROTOCOLS]));
338+
}
339+
340+
//--------------------------------------------------------------------
341+
342+
public function testAllowRedirectsOptionTrue()
343+
{
344+
$response = $this->request->request('get', 'http://example.com', [
345+
'allow_redirects' => true
346+
]);
347+
348+
$options = $this->request->curl_options;
349+
350+
$this->assertTrue(isset($options[CURLOPT_FOLLOWLOCATION]));
351+
$this->assertEquals(1, $options[CURLOPT_FOLLOWLOCATION]);
352+
353+
$this->assertTrue(isset($options[CURLOPT_MAXREDIRS]));
354+
$this->assertEquals(5, $options[CURLOPT_MAXREDIRS]);
355+
$this->assertTrue(isset($options[CURLOPT_REDIR_PROTOCOLS]));
356+
$this->assertEquals(CURLPROTO_HTTP|CURLPROTO_HTTPS, $options[CURLOPT_REDIR_PROTOCOLS]);
357+
}
358+
359+
//--------------------------------------------------------------------
360+
361+
public function testAllowRedirectsOptionDefaults()
362+
{
363+
$response = $this->request->request('get', 'http://example.com', [
364+
'allow_redirects' => true
365+
]);
366+
367+
$options = $this->request->curl_options;
368+
369+
$this->assertTrue(isset($options[CURLOPT_FOLLOWLOCATION]));
370+
$this->assertEquals(1, $options[CURLOPT_FOLLOWLOCATION]);
371+
372+
$this->assertTrue(isset($options[CURLOPT_MAXREDIRS]));
373+
$this->assertTrue(isset($options[CURLOPT_REDIR_PROTOCOLS]));
374+
}
375+
376+
//--------------------------------------------------------------------
325377
}

user_guide_src/source/libraries/curlrequest.rst

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,34 @@ Request Options
159159
This section describes all of the available options you may pass into the constructor, the ``request()`` method,
160160
or any of the shortcut methods.
161161

162+
allow_redirects
163+
===============
164+
165+
By default, cURL will follow all "Location:" headers the remote servers send back. The ``allow_redirects`` option
166+
allows you to modify how that works.
167+
168+
If you set the value to ``false``, then it will not follow any redirects at all::
169+
170+
$client->request('GET', 'http://example.com', ['allow_redirects' => false]);
171+
172+
Setting it to ``true`` will apply the default settings to the request::
173+
174+
$client->request('GET', 'http://example.com', ['allow_redirects' => true]);
162175

163-
Auth
176+
// Sets the following defaults:
177+
'max' => 5, // Maximum number of redirects to follow before stopping
178+
'strict' => true, // Ensure POST requests stay POST requests through redirects
179+
'protocols' => ['http', 'https'] // Restrict redirects to one or more protocols
180+
181+
You can pass in array as the value of the ``allow_redirects`` option to specify new settings in place of the defaults::
182+
183+
$client->request('GET', 'http://example.com', ['allow_redirects' => [
184+
'max' => 10,
185+
'protocols => ['https'] // Force HTTPS domains only.
186+
]]);
187+
188+
.. :note:: Following redirects does not work when PHP is in safe_mode or open_basedir is enabled.
189+
auth
164190
====
165191

166192
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``.::
171197

172198
$client->request('GET', 'http://example.com', ['auth' => ['username', 'password', 'digest']]);
173199

174-
Body
200+
body
175201
====
176202

177203
There are two ways to set the body of the request for request types that support them, like PUT, OR POST.
@@ -187,25 +213,25 @@ and functions the exact same way as the previous example. The value must be a st
187213

188214

189215

190-
Certificates
191-
============
216+
cert
217+
====
192218

193219
To specify the location of a PEM formatted client-side certificate, pass a string with the full path to the
194220
file as the ``cert`` option. If a password is required, set the value to an array with the first element
195221
as the path to the certificate, and the second as the password::
196222

197223
$client->request('get', '/', ['cert' => ['/path/server.pem', 'password']);
198224

199-
Connection Timeout
200-
==================
225+
Connect_timeout
226+
===============
201227

202228
By default, CodeIgniter does not impose a limit for cURL to attempt to connect to a website. If you need to
203229
modify this value, you can do so by passing the amount of time in seconds with the ``connect_timeout`` option.
204230
You can pass 0 to wait indefinitely::
205231

206232
$response->request('GET', 'http://example.com', ['connect_timeout' => 0]);
207233

208-
Debug
234+
debug
209235
=====
210236

211237
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
217243

218244
$response->request('GET', 'http://example.com', ['debug' => '/usr/local/curl_log.txt']);
219245

220-
Headers
246+
headers
221247
=======
222248

223249
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.::
235261
If headers are passed into the constructor they are treated as default values that will be overridden later by any
236262
further headers arrays or calls to ``setHeader()``.
237263

238-
Timeout
264+
timeout
239265
=======
240266

241267
By default, cURL functions are allowed to run as long as they take, with no time limit. You can modify this with the ``timeout``

0 commit comments

Comments
 (0)