diff --git a/includes/common.inc b/includes/common.inc index 3d73784..0ee0af3 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -544,15 +544,41 @@ function drupal_http_request($url, $headers = array(), $method = 'GET', $data = $result->request = $request; + // Maximum time that making and reading the request may take. + $total_time = variable_get('drupal_http_request_total_time', 30); + timer_start(__FUNCTION__); + stream_set_timeout($fp, $total_time); + fwrite($fp, $request); - // Fetch response. + // Fetch response. Due to PHP bugs like http://bugs.php.net/bug.php?id=43782 + // and http://bugs.php.net/bug.php?id=46049 we can't rely on feof(), but + // instead must invoke stream_get_meta_data() each iteration. + $info = stream_get_meta_data($fp); + $alive = !$info['eof'] && !$info['timed_out']; + $response = ''; - while (!feof($fp) && $chunk = fread($fp, 1024)) { + + while ($alive) { + $timeout = $total_time - timer_read(__FUNCTION__) / 1000; + if ($timeout <= 0) { + $info['timed_out'] = TRUE; + break; + } + stream_set_timeout($fp, floor($timeout), floor(1000000 * fmod($timeout, 1))); + $chunk = fread($fp, 1024); $response .= $chunk; + $info = stream_get_meta_data($fp); + $alive = !$info['eof'] && !$info['timed_out'] && $chunk; } fclose($fp); + if ($info['timed_out']) { + $result->code = 1; + $result->error = 'request timed out'; + return $result; + } + // Parse response. list($split, $result->data) = explode("\r\n\r\n", $response, 2); $split = preg_split("/\r\n|\n|\r/", $split);