Default, shared method for authenticating a connection to AWS.
Access
public
Parameters
Parameter |
Type |
Required |
Description |
---|---|---|---|
|
Required |
Indicates the operation to perform. |
|
|
Required |
An associative array of parameters for authenticating. See the individual methods for allowed keys. |
Returns
Type |
Description |
---|---|
Object containing a parsed HTTP response. |
Source
Method defined in sdk.class.php | Toggle source view (178 lines) | View on GitHub
public function authenticate($operation, $payload) { $original_payload = $payload; $method_arguments = func_get_args(); $curlopts = array(); $return_curl_handle = false; if (substr($operation, 0, strlen($this->operation_prefix)) !== $this->operation_prefix) { $operation = $this->operation_prefix . $operation; } // Extract the custom CURLOPT settings from the payload if (is_array($payload) && isset($payload['curlopts'])) { $curlopts = $payload['curlopts']; unset($payload['curlopts']); } // Determine whether the response or curl handle should be returned if (is_array($payload) && isset($payload['returnCurlHandle'])) { $return_curl_handle = isset($payload['returnCurlHandle']) ? $payload['returnCurlHandle'] : false; unset($payload['returnCurlHandle']); } // Use the caching flow to determine if we need to do a round-trip to the server. if ($this->use_cache_flow) { // Generate an identifier specific to this particular set of arguments. $cache_id = $this->key . '_' . get_class($this) . '_' . $operation . '_' . sha1(serialize($method_arguments)); // Instantiate the appropriate caching object. $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress); if ($this->delete_cache) { $this->use_cache_flow = false; $this->delete_cache = false; return $this->cache_object->delete(); } // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request. $data = $this->cache_object->response_manager(array($this, 'cache_callback'), $method_arguments); // Parse the XML body $data = $this->parse_callback($data); // End! return $data; } /*%******************************************************************************************%*/ // Signer $signer = new $this->auth_class($this->hostname, $operation, $payload, $this->credentials); $signer->key = $this->key; $signer->secret_key = $this->secret_key; $signer->auth_token = $this->auth_token; $signer->api_version = $this->api_version; $signer->utilities_class = $this->utilities_class; $signer->request_class = $this->request_class; $signer->response_class = $this->response_class; $signer->use_ssl = $this->use_ssl; $signer->proxy = $this->proxy; $signer->util = $this->util; $signer->registered_streaming_read_callback = $this->registered_streaming_read_callback; $signer->registered_streaming_write_callback = $this->registered_streaming_write_callback; $request = $signer->authenticate(); // Update RequestCore settings $request->request_class = $this->request_class; $request->response_class = $this->response_class; $request->ssl_verification = $this->ssl_verification; /*%******************************************************************************************%*/ // Debug mode if ($this->debug_mode) { $request->debug_mode = $this->debug_mode; } // Set custom CURLOPT settings if (count($curlopts)) { $request->set_curlopts($curlopts); } // Manage the (newer) batch request API or the (older) returnCurlHandle setting. if ($this->use_batch_flow) { $handle = $request->prep_request(); $this->batch_object->add($handle); $this->use_batch_flow = false; return $handle; } elseif ($return_curl_handle) { return $request->prep_request(); } // Send! $request->send_request(); // Prepare the response. $headers = $request->get_response_header(); $headers['x-aws-stringtosign'] = $signer->string_to_sign; if (isset($signer->canonical_request)) { $headers['x-aws-canonicalrequest'] = $signer->canonical_request; } $headers['x-aws-request-headers'] = $request->request_headers; $headers['x-aws-body'] = $signer->querystring; $data = new $this->response_class($headers, ($this->parse_the_response === true) ? $this->parse_callback($request->get_response_body()) : $request->get_response_body(), $request->get_response_code()); $response_body = (string) $request->get_response_body(); // Was it Amazon's fault the request failed? Retry the request until we reach $max_retries. if ( (integer) $request->get_response_code() === 500 || // Internal Error (presumably transient) (integer) $request->get_response_code() === 503) // Service Unavailable (presumably transient) { if ($this->redirects <= $this->max_retries) { // Exponential backoff $delay = (integer) (pow(4, $this->redirects) * 100000); usleep($delay); $this->redirects++; $data = $this->authenticate($operation, $original_payload); } } // DynamoDB has additional, custom logic for retrying requests else { // If the request to DynamoDB was throttled, we need to retry $need_to_retry_dynamodb_request = ( (integer) $request->get_response_code() === 400 && stripos($response_body, 'com.amazonaws.dynamodb.') !== false && stripos($response_body, 'ProvisionedThroughputExceededException') !== false ); // If the CRC32 of the response does not match the expected value, we need to retry $response_headers = $request->get_response_header(); if (!$need_to_retry_dynamodb_request && isset($response_headers['x-amz-crc32'])) { $crc32_expected = $response_headers['x-amz-crc32']; $crc32_actual = hexdec(hash('crc32b', $response_body)); $need_to_retry_dynamodb_request = ($crc32_expected != $crc32_actual); } // Perform retry if necessary using a more aggressive exponential backoff if ($need_to_retry_dynamodb_request) { if ($this->redirects === 0) { $this->redirects++; $data = $this->authenticate($operation, $original_payload); } elseif ($this->redirects <= max($this->max_retries, 10)) { // Exponential backoff $delay = (integer) (pow(2, ($this->redirects - 1)) * 50000); usleep($delay); $this->redirects++; $data = $this->authenticate($operation, $original_payload); } } } $this->redirects = 0; return $data; }