Created
January 18, 2012 19:41
-
-
Save jdmaturen/1635102 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| // … | |
| /** | |
| * Default, shared method for authenticating a connection to AWS. | |
| * | |
| * @param string $operation (Required) Indicates the operation to perform. | |
| * @param array $payload (Required) An associative array of parameters for authenticating. See the individual methods for allowed keys. | |
| * @return CFResponse Object containing a parsed HTTP response. | |
| */ | |
| 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()); | |
| // 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 custom logic | |
| elseif ( | |
| (integer) $request->get_response_code() === 400 && | |
| stripos((string) $request->get_response_body(), 'com.amazonaws.dynamodb.') !== false && ( | |
| stripos((string) $request->get_response_body(), 'ProvisionedThroughputExceededException') !== false | |
| ) | |
| ) | |
| { | |
| 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; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment