summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2009-06-06 15:43:05 +0000
committerDries Buytaert <dries@buytaert.net>2009-06-06 15:43:05 +0000
commit36e3d552cfe211cba22d1fc8cf0a7f4b13627179 (patch)
tree2350df7fe55052c45329e3818ec77421669525f6 /includes
parente9f8dc82b0a33c9d8c5a78267f79762ff5d884da (diff)
downloadbrdo-36e3d552cfe211cba22d1fc8cf0a7f4b13627179.tar.gz
brdo-36e3d552cfe211cba22d1fc8cf0a7f4b13627179.tar.bz2
- Patch #156582 by c960657, Damien Tournoud, townxelliot: added support for timeouts to drupal_http_request().
Diffstat (limited to 'includes')
-rw-r--r--includes/common.inc52
1 files changed, 39 insertions, 13 deletions
diff --git a/includes/common.inc b/includes/common.inc
index 299af56b8..35a1ccf46 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -56,6 +56,12 @@ define('JS_DEFAULT', 0);
define('JS_THEME', 100);
/**
+ * Error code indicating that the request made by drupal_http_request() exceeded
+ * the specified timeout.
+ */
+define('HTTP_REQUEST_TIMEOUT', 1);
+
+/**
* Add content to a specified region.
*
* @param $region
@@ -422,6 +428,10 @@ function drupal_access_denied() {
* - max_redirects
* An integer representing how many times a redirect may be followed.
* Defaults to 3.
+ * - timeout
+ * A float representing the maximum number of seconds the function call
+ * may take. The default is 30 seconds. If a timeout occurs, the error
+ * code is set to the HTTP_REQUEST_TIMEOUT constant.
* @return
* An object which can have one or more of the following parameters:
* - request
@@ -462,17 +472,28 @@ function drupal_http_request($url, array $options = array()) {
return $result;
}
+ timer_start(__FUNCTION__);
+
+ // Merge the default options.
+ $options += array(
+ 'headers' => array(),
+ 'method' => 'GET',
+ 'data' => NULL,
+ 'max_redirects' => 3,
+ 'timeout' => 30,
+ );
+
switch ($uri['scheme']) {
case 'http':
$port = isset($uri['port']) ? $uri['port'] : 80;
$host = $uri['host'] . ($port != 80 ? ':' . $port : '');
- $fp = @fsockopen($uri['host'], $port, $errno, $errstr, 15);
+ $fp = @fsockopen($uri['host'], $port, $errno, $errstr, $options['timeout']);
break;
case 'https':
// Note: Only works when PHP is compiled with OpenSSL support.
$port = isset($uri['port']) ? $uri['port'] : 443;
$host = $uri['host'] . ($port != 443 ? ':' . $port : '');
- $fp = @fsockopen('ssl://' . $uri['host'], $port, $errno, $errstr, 20);
+ $fp = @fsockopen('ssl://' . $uri['host'], $port, $errno, $errstr, $options['timeout']);
break;
default:
$result->error = 'invalid schema ' . $uri['scheme'];
@@ -501,14 +522,6 @@ function drupal_http_request($url, array $options = array()) {
$path .= '?' . $uri['query'];
}
- // Merge the default options.
- $options += array(
- 'headers' => array(),
- 'method' => 'GET',
- 'data' => NULL,
- 'max_redirects' => 3,
- );
-
// Merge the default headers.
$options['headers'] += array(
'User-Agent' => 'Drupal (+http://drupal.org/)',
@@ -553,8 +566,16 @@ function drupal_http_request($url, array $options = array()) {
// Fetch response.
$response = '';
- while (!feof($fp) && $chunk = fread($fp, 1024)) {
- $response .= $chunk;
+ while (!feof($fp)) {
+ // Calculate how much time is left of the original timeout value.
+ $timeout = $options['timeout'] - timer_read(__FUNCTION__) / 1000;
+ if ($timeout <= 0) {
+ $result->code = HTTP_REQUEST_TIMEOUT;
+ $result->error = 'request timed out';
+ return $result;
+ }
+ stream_set_timeout($fp, floor($timeout), floor(1000000 * fmod($timeout, 1)));
+ $response .= fread($fp, 1024);
}
fclose($fp);
@@ -639,7 +660,12 @@ function drupal_http_request($url, array $options = array()) {
case 302: // Moved temporarily
case 307: // Moved temporarily
$location = $result->headers['Location'];
- if ($options['max_redirects']) {
+ $options['timeout'] -= timer_read(__FUNCTION__) / 1000;
+ if ($options['timeout'] <= 0) {
+ $result->code = HTTP_REQUEST_TIMEOUT;
+ $result->error = 'request timed out';
+ }
+ elseif ($options['max_redirects']) {
// Redirect to the new location.
$options['max_redirects']--;
$result = drupal_http_request($location, $options);