Commit e6a4b82e authored by Gábor Hojtsy's avatar Gábor Hojtsy

#196535 by sun, chx, dww: check whether Drupal can issue HTTP requests at all,...

#196535 by sun, chx, dww: check whether Drupal can issue HTTP requests at all, so we know that this is the cause of problems, not the remote host not responding.
parent d8bd6cf9
......@@ -37,6 +37,17 @@ you will need PHP's XML extension. This extension is enabled by default.
- If you want support for clean URLs, you'll need mod_rewrite and the ability
to use local .htaccess files.
- Various Drupal features require that the web server process (for
example, httpd) needs to be able to initiate outbound connections.
This is usually possible, but some hosting providers or server
configurations forbid such connections. The features that depend on
this functionality include the integrated "Update status" module
which downloads information about available updates of Drupal core
and any installed contributed modules and themes, the ability to log
in via OpenID, fetching aggregator feeds, or use other
network-dependent services.
INSTALLATION
------------
......
......@@ -415,7 +415,23 @@ function drupal_access_denied() {
* data and redirect status.
*/
function drupal_http_request($url, $headers = array(), $method = 'GET', $data = NULL, $retry = 3) {
static $self_test = FALSE;
$result = new stdClass();
// Try to clear the drupal_http_request_fails variable if it's set. We
// can't tie this call to any error because there is no surefire way to
// tell whether a request has failed, so we add the check to places where
// some parsing has failed.
if (!$self_test && variable_get('drupal_http_request_fails', FALSE)) {
$self_test = TRUE;
$works = module_invoke('system', 'check_http_request');
$self_test = FALSE;
if (!$works) {
// Do not bother with further operations if we already know that we
// have no chance.
$result->error = t("The server can't issue HTTP requests");
return $result;
}
}
// Parse the URL and make sure we can handle the schema.
$uri = parse_url($url);
......@@ -439,8 +455,8 @@ function drupal_http_request($url, $headers = array(), $method = 'GET', $data =
// Make sure the socket opened properly.
if (!$fp) {
// When a network error occurs, we make sure that it is a negative number so
// it can clash with the HTTP status codes.
// When a network error occurs, we use a negative number so it does not
// clash with the HTTP status codes.
$result->code = -$errno;
$result->error = trim($errstr);
return $result;
......
......@@ -350,6 +350,7 @@ function xmlrpc_error($code = NULL, $message = NULL) {
$xmlrpc_error->is_error = TRUE;
$xmlrpc_error->code = $code;
$xmlrpc_error->message = $message;
module_invoke('system', 'check_http_request');
}
return $xmlrpc_error;
}
......
......@@ -600,7 +600,7 @@ function aggregator_refresh($feed) {
case 301:
$feed['url'] = $result->redirect_url;
watchdog('aggregator', 'Updated URL for feed %title to %url.', array('%title' => $feed['title'], '%url' => $feed['url']));
// Deliberate no break.
case 200:
case 302:
case 307:
......@@ -648,11 +648,14 @@ function aggregator_refresh($feed) {
watchdog('aggregator', 'There is new syndicated content from %site.', array('%site' => $feed['title']));
drupal_set_message(t('There is new syndicated content from %site.', array('%site' => $feed['title'])));
break;
}
break;
$result->error = t('feed not parseable');
// Deliberate no break.
default:
watchdog('aggregator', 'The feed from %site seems to be broken, due to "%error".', array('%site' => $feed['title'], '%error' => $result->code .' '. $result->error), WATCHDOG_WARNING);
drupal_set_message(t('The feed from %site seems to be broken, because of error "%error".', array('%site' => $feed['title'], '%error' => $result->code .' '. $result->error)));
module_invoke('system', 'check_http_request');
}
}
......
......@@ -290,6 +290,9 @@ function openid_discovery($claimed_id) {
}
}
}
if (!$services) {
module_invoke('system', 'check_http_request');
}
return $services;
}
......@@ -321,12 +324,14 @@ function openid_association($op_endpoint) {
$assoc_headers = array('Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8');
$assoc_result = drupal_http_request($op_endpoint, $assoc_headers, 'POST', $assoc_message);
if (isset($assoc_result->error)) {
module_invoke('system', 'check_http_request');
return FALSE;
}
$assoc_response = _openid_parse_message($assoc_result->data);
if (isset($assoc_response['mode']) && $assoc_response['mode'] == 'error') {
return FALSE;
module_invoke('system', 'check_http_request');
return FALSE;
}
if ($assoc_response['session_type'] == 'DH-SHA1') {
......@@ -487,6 +492,8 @@ function openid_verify_assertion($op_endpoint, $response) {
}
}
}
if (!$valid) {
module_invoke('system', 'check_http_request');
}
return $valid;
}
......@@ -241,6 +241,14 @@ function system_requirements($phase) {
$requirements['update status'] = array(
'value' => $t('Enabled'),
);
if (variable_get('drupal_http_request_fails', FALSE)) {
$requirements['http requests'] = array(
'title' => $t('HTTP request status'),
'value' => $t('Fails'),
'severity' => REQUIREMENT_ERROR,
'description' => $t('Your system or network configuration does not allow Drupal to access web pages, resulting in reduced functionality. This could be due to your webserver configuration or PHP settings, and should be resolved in order to download information about available updates, fetch aggregator feeds, sign in via OpenID, or use other network-dependent services.'),
);
}
}
$requirements['update status']['title'] = $t('Update notifications');
}
......
......@@ -445,6 +445,15 @@ function system_menu() {
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
// Menu handler to test that drupal_http_request() works locally.
// @see system_check_http_request().
$items['admin/reports/request-test'] = array(
'title' => 'Request test',
'page callback' => 'printf',
'page arguments' => array('request test'),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
// Reports:
$items['admin/reports'] = array(
......@@ -1811,6 +1820,32 @@ function _system_zonelist() {
return $zones;
}
/**
* Checks whether the server is capable of issuing HTTP requests.
*
* The function sets the drupal_http_request_fail system variable to TRUE if
* drupal_http_request() does not work and then the system status report page
* will contain an error.
*
* @return
* Whether the admin/reports/request-test page can be requested via HTTP
* and contains the same output as if called via the menu system.
*/
function system_check_http_request() {
// Check whether we can do any request at all. First get the results for
// a very simple page which has access TRUE set via the menu system. Then,
// try to drupal_http_request() the same page and compare.
ob_start();
$path = 'admin/reports/request-test';
menu_execute_active_handler($path);
$nothing = ob_get_contents();
ob_end_clean();
$result = drupal_http_request(url($path, array('absolute' => TRUE)));
$works = isset($result->data) && $result->data == $nothing;
variable_set('drupal_http_request_fails', !$works);
return $works;
}
/**
* Format the Powered by Drupal text.
*
......
......@@ -42,12 +42,15 @@ function _update_refresh() {
if ($data) {
$parser = new update_xml_parser;
$available = $parser->parse($data);
}
if (!empty($available) && is_array($available)) {
$frequency = variable_get('update_check_frequency', 1);
cache_set('update_info', $available, 'cache_update', time() + (60 * 60 * 24 * $frequency));
variable_set('update_last_check', time());
watchdog('update', 'Fetched information about all available new releases and updates.', array(), WATCHDOG_NOTICE, l('view', 'admin/reports/updates'));
}
else {
module_invoke('system', 'check_http_request');
watchdog('update', 'Unable to fetch any information about available new releases and updates.', array(), WATCHDOG_ERROR, l('view', 'admin/reports/updates'));
}
return $available;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment