diff --git a/httprl.module b/httprl.module index 2f8f4b8..3a9ee7a 100644 --- a/httprl.module +++ b/httprl.module @@ -28,7 +28,7 @@ define('HTTPRL_REQUEST_ALLOWED_REDIRECTS_EXHAUSTED', -2); define('HTTPRL_REQUEST_FWRITE_FAIL', -3); /** - * Error code indicating that all requests made by httprl_send_request() + * Error code indicating that all requests made by httprl_send_request * exceeded the specified timeout. */ define('HTTPRL_FUNCTION_TIMEOUT', -4); @@ -234,35 +234,23 @@ function httprl_build_url_self($path = '', $detect_schema = FALSE) { * String containing the URL to be parsed by parse_url(). * @param &$result * Result object; used only for error handling in this function. - * @param &$return - * Return array; used only for error handling in this function. - * @param $options - * Options array; used only for error handling in this function. * * @return $uri * Array from parse_url(). */ -function httprl_parse_url($url, &$result, &$return, $options) { +function httprl_parse_url($url, &$result) { // Parse the URL and make sure we can handle the schema. $uri = @parse_url($url); if (empty($uri)) { + // Set error code for failed request. $result->error = 'Unable to parse URL.'; $result->code = HTTPRL_URL_PARSE_ERROR; - - // Add in failed request to the output. - // Continue if the URL passed in is bad. - $return[$url] = httprl_send_request(FALSE, $url, $result, $options); - return FALSE; } - if (!isset($uri['scheme'])) { + elseif (!isset($uri['scheme'])) { + // Set error code for failed request. $result->error = 'Missing schema.'; $result->code = HTTPRL_URL_MISSING_SCHEMA; - - // Add in failed request to the output. - // Continue if no scheme was passed in. - $return[$url] = httprl_send_request(FALSE, $url, $result, $options); - return FALSE; } return $uri; @@ -368,15 +356,12 @@ function httprl_setup_proxy(&$uri, &$options, $url) { * String containing the proxy servers host name if one is to be used. * @param &$result * Result object; used only for error handling in this function. - * @param &$return - * Return array; used only for error handling in this function. - * @param $url - * String containing the URL. * * @return $socket * String containing the TCP/SSL socket connection URI. */ -function httprl_set_socket($uri, &$options, $proxy_server, &$result, &$return, $url) { +function httprl_set_socket($uri, &$options, $proxy_server, &$result) { + $socket = ''; switch ($uri['scheme']) { case 'proxy': // Make the socket connection to a proxy server. @@ -417,10 +402,6 @@ function httprl_set_socket($uri, &$options, $proxy_server, &$result, &$return, $ $result->error = 'Invalid schema ' . $uri['scheme'] . '.'; $result->code = HTTPRL_URL_INVALID_SCHEMA; - // Add in failed request to the output. - // Continue if an invalid scheme was passed in. - $return[$url] = httprl_send_request(FALSE, $url, $result, $options); - return FALSE; } return $socket; @@ -542,7 +523,9 @@ function httprl_handle_data(&$options) { /** * Multipart encode a data array. * - * PHP has http_build_query() which will url-encode data. There is no built in function to multipart encode data thus we have this function below. + * PHP has http_build_query() which will url-encode data. There is no built in + * function to multipart encode data thus we have this function below. + * * @param $uri * Array from parse_url(). * @param &$options @@ -612,8 +595,107 @@ function httprl_build_request_string($uri, $options) { return $request; } + +/** + * Read the error number & string and give a nice looking error in the output. + * + * This is a flexible and powerful HTTP client implementation. Correctly + * handles GET, POST, PUT or any other HTTP requests. + * + * @param $errno + * Error number from stream_socket_client(). + * @param $errstr + * Error string from stream_socket_client(). + * @param $socket + * An integer holding the stream timeout value. + * @param $result + * An object for httprl_send_request. + * @return $result + * An object for httprl_send_request. + */ +function httprl_stream_connection_error_formatter($errno, $errstr, $socket, $result) { + // Make sure drupal_convert_to_utf8() is available. + if (defined('VERSION') && substr(VERSION, 0, 1) >= 7) { + require_once DRUPAL_ROOT . '/includes/unicode.inc'; + } + else { + require_once './includes/unicode.inc'; + } + // Convert error message to utf-8. Using ISO-8859-1 (Latin-1) as source + // encoding could be wrong; it is a simple workaround :) + $errstr = trim(drupal_convert_to_utf8($errstr, 'ISO-8859-1')); + if (!$errno) { + // If $errno is 0, it is an indication that the error occurred + // before the connect() call. This is most likely due to a problem + // initializing the stream. + $result->code = HTTPRL_ERROR_INITIALIZING_STREAM; + $result->error = !empty($errstr) ? $errstr : t('Error initializing socket @socket.', array('@socket' => $socket)); + } + else { + // When a network error occurs, we use a negative number so it does not + // clash with the HTTP status codes. + $result->code = (int) -$errno; + $result->error = !empty($errstr) ? $errstr : t('Error opening socket @socket.', array('@socket' => $socket)); + } + return $result; +} + +/** + * Use stream_socket_client() to create a connection to the server. + * + * @param $socket + * An integer holding the stream timeout value. + * @param $flags + * STREAM_CLIENT_CONNECT or STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT. + * @param $uri + * Array from parse_url(). + * @param $options + * Array containing options. Used for timeout and async_connect here. + * @return array + * array($fp, $options, $errno, $errstr). + */ +function httprl_establish_stream_connection($socket, $flags, $uri, $options) { + // Start the timer. + $timer_name = mt_rand(); + timer_start($timer_name); + $fp = FALSE; + + // Try to make a connection, 3 max tries in loop. + $count = 0; + while (!$fp && $count < 3) { + // Try the connection again not using async if in https mode. + if ($count > 0) { + if ($flags === STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT && $uri['scheme'] == 'https') { + $flags = STREAM_CLIENT_CONNECT; + $options['async_connect'] = FALSE; + } + else { + // Break out of while loop if we can't connect. + break; + } + } + + // Open the connection. + if (empty($options['context'])) { + $fp = @stream_socket_client($socket, $errno, $errstr, $options['timeout'], $flags); + } + else { + // Create a stream with context. Context allows for the verification of + // a SSL certificate. + $fp = @stream_socket_client($socket, $errno, $errstr, $options['timeout'], $flags, $options['context']); + } + $count++; + $options['timeout'] = $options['timeout'] - timer_read($timer_name) / 1000; + } + + // Stop the timer. + timer_stop($timer_name); + + return array($fp, $options, $errno, $errstr); +} + /** - * Queue up a HTTP request in httprl_send_request(). + * Queue up a HTTP request in httprl_send_request. * * @see drupal_http_request() * @@ -675,13 +757,13 @@ function httprl_build_request_string($uri, $options) { * will be available to the parent. * - alter_all_streams_function: Function name. This function runs at the end * of httprl_post_processing() so that one can alter the $responses and - * $streams variables inside of httprl_send_request(). Defined function + * $streams variables inside of httprl_send_request. Defined function * should have the following parameters: * ($id, &$responses, &$streams, $current_time). * * @return array * Array where key is the URL and the value is the return value from - * httprl_send_request(). + * httprl_send_request. */ function httprl_request($urls, $options = array()) { // See if a full bootstrap has been done. @@ -710,8 +792,10 @@ function httprl_request($urls, $options = array()) { $result = new stdClass(); // Parse the given URL and skip if an error occurred. - $uri = httprl_parse_url($url, $result, $return, $options); - if (empty($uri)) { + $uri = httprl_parse_url($url, $result); + if (isset($result->error)) { + // Add the failed request to the output. + $return[$url] = httprl_send_request(FALSE, $url, $result, $options); continue; } // Setup the default options. @@ -721,7 +805,9 @@ function httprl_request($urls, $options = array()) { $proxy_server = httprl_setup_proxy($uri, $options, $url); // Create the socket string and skip if an error occurred. $socket = httprl_set_socket($uri, $options, $proxy_server, $result, $return, $url); - if (empty($socket)) { + if (isset($result->error)) { + // Add the failed request to the output. + $return[$url] = httprl_send_request(FALSE, $url, $result, $options); continue; } @@ -777,104 +863,6 @@ function httprl_request($urls, $options = array()) { } /** - * Read the error number & string and give a nice looking error in the output. - * - * This is a flexible and powerful HTTP client implementation. Correctly - * handles GET, POST, PUT or any other HTTP requests. - * - * @param $errno - * Error number from stream_socket_client(). - * @param $errstr - * Error string from stream_socket_client(). - * @param $socket - * An integer holding the stream timeout value. - * @param $result - * An object for httprl_send_request. - * @return $result - * An object for httprl_send_request. - */ -function httprl_stream_connection_error_formatter($errno, $errstr, $socket, $result) { - // Make sure drupal_convert_to_utf8() is available. - if (defined('VERSION') && substr(VERSION, 0, 1) >= 7) { - require_once DRUPAL_ROOT . '/includes/unicode.inc'; - } - else { - require_once './includes/unicode.inc'; - } - // Convert error message to utf-8. Using ISO-8859-1 (Latin-1) as source - // encoding could be wrong; it is a simple workaround :) - $errstr = trim(drupal_convert_to_utf8($errstr, 'ISO-8859-1')); - if (!$errno) { - // If $errno is 0, it is an indication that the error occurred - // before the connect() call. This is most likely due to a problem - // initializing the stream. - $result->code = HTTPRL_ERROR_INITIALIZING_STREAM; - $result->error = !empty($errstr) ? $errstr : t('Error initializing socket @socket.', array('@socket' => $socket)); - } - else { - // When a network error occurs, we use a negative number so it does not - // clash with the HTTP status codes. - $result->code = (int) -$errno; - $result->error = !empty($errstr) ? $errstr : t('Error opening socket @socket.', array('@socket' => $socket)); - } - return $result; -} - -/** - * Use stream_socket_client() to create a connection to the server. - * - * @param $socket - * An integer holding the stream timeout value. - * @param $flags - * STREAM_CLIENT_CONNECT or STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT. - * @param $uri - * Array from parse_url(). - * @param $options - * Array containing options. Used for timeout and async_connect here. - * @return array - * array($fp, $options, $errno, $errstr). - */ -function httprl_establish_stream_connection($socket, $flags, $uri, $options) { - // Start the timer. - $timer_name = mt_rand(); - timer_start($timer_name); - $fp = FALSE; - - // Try to make a connection, 3 max tries in loop. - $count = 0; - while (!$fp && $count < 3) { - // Try the connection again not using async if in https mode. - if ($count > 0) { - if ($flags === STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT && $uri['scheme'] == 'https') { - $flags = STREAM_CLIENT_CONNECT; - $options['async_connect'] = FALSE; - } - else { - // Break out of while loop if we can't connect. - break; - } - } - - // Open the connection. - if (empty($options['context'])) { - $fp = @stream_socket_client($socket, $errno, $errstr, $options['timeout'], $flags); - } - else { - // Create a stream with context. Context allows for the verification of - // a SSL certificate. - $fp = @stream_socket_client($socket, $errno, $errstr, $options['timeout'], $flags, $options['context']); - } - $count++; - $options['timeout'] = $options['timeout'] - timer_read($timer_name) / 1000; - } - - // Stop the timer. - timer_stop($timer_name); - - return array($fp, $options, $errno, $errstr); -} - -/** * Perform many HTTP requests. * * @see drupal_http_request() @@ -1595,7 +1583,7 @@ function httprl_run_callback(&$result) { * be the first argument of the function. */ function httprl_queue_background_callback(&$args, &$result = NULL) { - // Use a counter to prevent key collisions in httprl_send_request(). + // Use a counter to prevent key collisions in httprl_send_request. static $counter; if (!isset($counter)) { $counter = 0;