diff --git a/httprl.admin.inc b/httprl.admin.inc new file mode 100644 index 0000000..257e058 --- /dev/null +++ b/httprl.admin.inc @@ -0,0 +1,41 @@ + 'textfield', + '#title' => t('IP Address to send all self server requests to'), + '#default_value' => variable_get('httprl_server_addr', FALSE), + '#description' => t('If left blank it will use the same server as the request. If set to -1 it will use the host name instead of an IP address. This controls the output of httprl_build_url_self()'), + ); + + return system_settings_form($form); +} + +/** + * Validate form values. + */ +function httprl_admin_settings_form_validate($form, &$form_state) { + $advagg_server_addr = $form_state['values']['httprl_server_addr']; + + // If the IP field is not blank, check that its a valid address. + if ( !empty($advagg_server_addr) + && $advagg_server_addr != -1 + && ip2long($advagg_server_addr) === FALSE + ) { + form_set_error('httprl_server_addr', t('Must be a valid IP address.')); + } +} diff --git a/httprl.install b/httprl.install index 0189757..cc74899 100644 --- a/httprl.install +++ b/httprl.install @@ -61,6 +61,7 @@ function httprl_requirements($phase) { } if ($phase == 'runtime') { $url_path = 'admin/httprl-test'; + // Check that the menu router handler is working. If it's not working the rest // of the tests are pointless. $item = menu_get_item($url_path); @@ -76,12 +77,11 @@ function httprl_requirements($phase) { } // Test the non blocking url - global $base_root, $base_path; - // Build URL to point to admin/httprl-test on this server. - $ip = empty($_SERVER['SERVER_ADDR']) ? '127.0.0.1' : $_SERVER['SERVER_ADDR']; + global $base_root, $base_path, $conf; $id = 'httprl_' . md5(mt_rand() . time()); - $url_ip = 'http://' . $ip . $base_path . $url_path . '?key=' . md5(drupal_get_private_key()) . '&id=' . $id; - $url_host = $base_root . $base_path . $url_path . '?key=' . md5(drupal_get_private_key()) . '&id=' . $id; + // Build URL to point to admin/httprl-test on this server. + $url = httprl_build_url_self($url_path . '?key=' . md5(drupal_get_private_key()) . '&id=' . $id); + // Set the headers to point to this hostname. $headers = array( 'Host' => $_SERVER['HTTP_HOST'], @@ -99,21 +99,65 @@ function httprl_requirements($phase) { lock_acquire($id, 6); // Queue up the requests & execute them. - httprl_request($url_ip, $options); - httprl_request($url_host, $options); + httprl_request($url, $options); $requests = httprl_send_request(); // Wait for the lock and stop the timer. lock_wait($id); $time = timer_stop($id); if (($time['time'] / 1000) > 5) { - // Lock timed out and was not reset by the URL ping. - $requirements['httprl_nonblocking'] = array( - 'title' => $t('HTTPRL - Non Blocking'), - 'severity' => REQUIREMENT_WARNING, - 'value' => $t('This server does not handle hanging connections.'), - 'description' => $t('Using non blocking mode on this server my not work correctly. More info: !info', array('!info' => str_replace(' ', '    ', nl2br(htmlentities(print_r(array($time, $requests), TRUE)))))), - ); + $ip = variable_get('httprl_server_addr', FALSE); + $lasttime = ''; + $lastrequests = ''; + if (empty($ip)) { + $lasttime = $time; + $lastrequests = $requests; + $conf['httprl_server_addr'] = -1; + + // If lock failed to release in time, try not using an IP when calling self. + $id = 'httprl_' . md5(mt_rand() . time()); + // Build URL to point to admin/httprl-test on this server. + + + $url = httprl_build_url_self($url_path . '?key=' . md5(drupal_get_private_key()) . '&id=' . $id); + + // Set the headers to point to this hostname. + $headers = array( + 'Host' => $_SERVER['HTTP_HOST'], + ); + + // Add in the headers and set the blocking mode. + $options = array( + 'headers' => $headers, + 'blocking' => FALSE, + 'timeout' => 6.0, + ); + + // Start the timer & Get a lock. + timer_start($id); + lock_acquire($id, 6); + + // Queue up the requests & execute them. + httprl_request($url, $options); + $requests = httprl_send_request(); + + // Wait for the lock and stop the timer. + lock_wait($id); + $time = timer_stop($id); + } + if (($time['time'] / 1000) > 5) { + // Lock timed out and was not reset by the URL ping. + $requirements['httprl_nonblocking'] = array( + 'title' => $t('HTTPRL - Non Blocking'), + 'severity' => REQUIREMENT_WARNING, + 'value' => $t('This server does not handle hanging connections.'), + 'description' => $t('Using non blocking mode on this server my not work correctly. More info: !info', array('!info' => str_replace(' ', '    ', nl2br(htmlentities(print_r(array($time, $requests, $lasttime, $lastrequests), TRUE)))))), + ); + } + else { + // Request worked when using the hostname not the ip. + variable_set('httprl_server_addr', -1); + } } } diff --git a/httprl.module b/httprl.module index 04b38e1..ad0e9a2 100755 --- a/httprl.module +++ b/httprl.module @@ -17,6 +17,7 @@ define('HTTP_REQUEST_FWRITE_FAIL', -2); */ function httprl_menu() { $items = array(); + // Non blocking test URL. $items['admin/httprl-test'] = array( 'title' => 'HTTPRL', 'page callback' => 'httprl_nonblockingtest_page', @@ -25,10 +26,76 @@ function httprl_menu() { 'type' => MENU_CALLBACK, 'file' => 'httprl.nonblocktest.inc', ); + + // Different versions of drupal use a different path for settings. + if (version_compare(VERSION, '7.0') >= 0) { + $config_url = 'admin/config/development/httprl'; + } + else { + $config_url = 'admin/settings/httprl'; + } + $items[$config_url] = array( + 'title' => 'HTTPRL', + 'description' => 'Configure HTTPRL Settings.', + 'access arguments' => array('administer site configuration'), + 'page callback' => 'httprl_admin_settings_page', + 'type' => MENU_NORMAL_ITEM, + 'file' => 'httprl.admin.inc', + ); + return $items; } /** + * Helper function to build an URL for asynchronous requests to self. + * + * @param $path + * Path to a URI excluding everything to the left and including the base path. + * @param $detect_schema + * If TRUE it will see if this request is https; if so, it will set the full + * url to be https as wel. + */ +function httprl_build_url_self($path = '', $detect_schema = FALSE) { + global $base_path; + + // Server auth. + $auth = ''; + if (isset($_SERVER['AUTH_TYPE']) && $_SERVER['AUTH_TYPE'] == 'Basic') { + $auth = $_SERVER['PHP_AUTH_USER'] . ':' . $_SERVER['PHP_AUTH_PW'] .'@'; + } + + // Host. + $ip = variable_get('httprl_server_addr', FALSE); + if ($ip == -1) { + $ip = $_SERVER['HTTP_HOST']; + } + elseif (empty($ip)) { + $ip = empty($_SERVER['SERVER_ADDR']) ? '127.0.0.1' : $_SERVER['SERVER_ADDR']; + } + + // Port. + $port = ''; +// if ( isset($_SERVER['SERVER_PORT']) +// && is_numeric($_SERVER['SERVER_PORT']) +// && ($_SERVER['SERVER_PORT'] != 80 || $_SERVER['SERVER_PORT'] != 443) +// ) { +// $port = ':' . $_SERVER['SERVER_PORT']; +// } + + // http or https. + $schema = 'http://'; + if ( $detect_schema && ( + (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') + || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') + || (isset($_SERVER['HTTP_HTTPS']) && $_SERVER['HTTP_HTTPS'] == 'on') + )) { + $schema = 'https://'; + } + + return $schema . $auth . $ip . $port . $base_path . $path; +} + +/** * Perform an HTTP request * * @see drupal_http_request()