diff --git a/lib/CleantalkSP/Common/RemoteCalls.php b/lib/CleantalkSP/Common/RemoteCalls.php index 7f59fb7ab..678fe3659 100644 --- a/lib/CleantalkSP/Common/RemoteCalls.php +++ b/lib/CleantalkSP/Common/RemoteCalls.php @@ -35,6 +35,17 @@ class RemoteCalls const COOLDOWN = 10; + /** + * Timeout (seconds) for RC self-test requests. + * Keep low: expected response is immediate "OK". + */ + const TEST_REQUEST_TIMEOUT = 7; + + /** + * How many times to attempt RC self-test before giving up. + */ + const TEST_REQUEST_ATTEMPTS = 3; + /** * Checking if the current request is the Remote Call * @@ -211,40 +222,51 @@ public static function performTest($host, $params, $patterns = array()) { // Delete async pattern to get the result in this process $key = array_search('async', $patterns, true); - if ($key) { + if ($key !== false) { unset($patterns[$key]); } // Adding test flag $params = array_merge($params, array('test' => 'test')); - // Perform test request - $http = new \CleantalkSP\Common\HTTP\Request(); - $result = $http - ->setUrl($host) - ->setData($params) - ->setPresets($patterns) - ->request(); - $error_template = 'WRONG_SITE_RESPONSE TEST_ACTION FOR RC %s, ERROR: %s'; + $error = null; + + for ($attempt = 1; $attempt <= self::TEST_REQUEST_ATTEMPTS; $attempt++) { + $error = null; + + $http = new \CleantalkSP\Common\HTTP\Request(); + $options = defined('CURLOPT_TIMEOUT') + ? array(CURLOPT_TIMEOUT => self::TEST_REQUEST_TIMEOUT) + : array('timeout' => self::TEST_REQUEST_TIMEOUT); + $result = $http + ->setUrl($host) + ->setData($params) + ->setPresets($patterns) + // Prefer CURLOPT_* int keys: string 'timeout' is left in options by Request + // converter and breaks curl_setopt_array() on PHP 8+. Fallback to string + // name only when cURL constants are unavailable (no cURL extension). + ->setOptions($options) + ->request(); + + // Considering empty response as error + if ($result === '') { + $error = sprintf($error_template, $params['spbc_remote_call_action'], 'EMPTY RESPONSE'); + // Wrap and pass error + } elseif (is_array($result) && ! empty($result['error'])) { + $error = sprintf($error_template, $params['spbc_remote_call_action'], $result['error']); + // Expects 'OK' string as good response otherwise - error + } elseif (is_string($result) && ! preg_match('@^.*?OK$@', $result)) { + $unexpected_response = 'UNEXPECTED RESPONSE: "' . json_encode(substr($result, 0, 400)) . '"'; + $error = sprintf($error_template, $params['spbc_remote_call_action'], $unexpected_response); + } - // Considering empty response as error - if ($result === '') { - $error = sprintf($error_template, $params['spbc_remote_call_action'], 'EMPTY RESPONSE'); - // Wrap and pass error - } elseif (! empty($result['error'])) { - $error = sprintf($error_template, $params['spbc_remote_call_action'], $result['error']); - // Expects 'OK' string as good response otherwise - error - } elseif (is_string($result) && ! preg_match('@^.*?OK$@', $result)) { - $unexpected_response = 'UNEXPECTED RESPONSE: "' . json_encode(substr($result, 0, 400)) . '"'; - $error = sprintf($error_template, $params['spbc_remote_call_action'], $unexpected_response); - } - - if (!empty($error)) { - $result = array('error' => $error); + if ($error === null) { + return $result; + } } - return $result; + return array('error' => $error); } /**