/** * This method is a slightly modified version of the one in the parent API Client class. Rather * that taking in an API token and performing requests this method takes in an API key which is * then used to retrieve an API token from the API (authenticate) and then makes requests to the * client reference being decorated. * * @param string $key The API key to be used to authenticate with the API. * @param string $resource The API endpoint the request should be made to. * @param string $method The HTTP verb that should be used to make the request. * @param array $data Any data that should be passed along with the request. * @param array $headers The HTTP headers to be sent with the request. * @param array $options Extra options that may be passed into the request. This argument * mostly exists to facilitate the decorators. Possible keys used by * this decorator include 'reAuth' and 'attempts' * * @return array The API response structure. * */ public function sendRequest($key, $resource, $method = "GET", array $data = array(), array $headers = array(), array $options = array()) { // Apply some default values for options that we may not get. $options['reAuth'] = array_key_exists('reAuth', $options) ? $options['reAuth'] : false; $options['attempts'] = array_key_exists('attempts', $options) ? $options['attempts'] : 1; // Get an array of the arguments to this function call. $args = func_get_args(); // Retrieve authentication information. $auth = $this->authenticate($key, array(), array('force' => $options['reAuth'])); $token = $auth['responseData']['data']['api_token']; /* Since we will be passing the token instead of key we want to add the key to the options so that we may refer to it later (hint: in the caching decorator) */ $options['key'] = $key; try { // Forward the request on to the API Client. $result = $this->client->sendRequest($token, $resource, $method, $data, $headers, $options); } catch (Wolfnet_Api_ApiException $e) { $e->append('Several attempts were made.'); $e->append($e->getCode() === Wolfnet_Api_Client::AUTH_ERROR ? 'auth-code' : '!auth-code'); $e->append($options['attempts'] < 5 ? 'attempts' : '!attempts'); if ($e->getCode() === Wolfnet_Api_Client::AUTH_ERROR && $options['attempts'] < 5) { $options['reAuth'] = true; // This will force the authentication to bypass caching $options['attempts']++; $result = $this->sendRequest($key, $resource, $method, $data, $headers, $options); } elseif ($options['attempts'] > 1) { throw $e->append('Several attempts were made.'); } else { throw $e; } } return $result; }
/** * This method will first attempt to retrieve the request from the cache when appropriate. If * no value is found in the cache it will defer the request to the API client being decorated * and will then cache the response if appropriate. * * NOTE: Only GET requests should be cached per HTTP specs * * @param string $token The API token to be used to make the request. * @param string $resource The API endpoint the request should be made to. * @param string $method The HTTP verb that should be used to make the request. * @param array $data Any data that should be passed along with the request. * @param array $headers The HTTP headers to be sent with the request. * @param array $options Extra options that may be passed into the request. This argument * mostly exists to facilitate the decorators. Possible keys used by * this decorator include 'key' and 'force'. * * @return array The API response structure. * */ public function sendRequest($token, $resource, $method = "GET", array $data = array(), array $headers = array(), array $options = array()) { $args = func_get_args(); $result = null; /* Attempt to retrieve a 'key' value from the options argument which will be use to uniquely * identify requests being made for that specific key. If none is present we fall back to * the token which is even more unique. */ $options['key'] = array_key_exists('key', $options) ? $options['key'] : $token; /* Attempt to retrieve the 'cache' value from the options argument. */ $options['cache'] = array_key_exists('cache', $options) ? $options['cache'] : true; /* If the force key is present we should force the decorator to retrieve new data from the * API even if cached data was found. */ $options['force'] = array_key_exists('force', $options) ? $options['force'] : false; // The request is not a GET request we should not be caching. if ($method != 'GET') { $options['cache'] = false; } // Generate a cache key if appropriate $cacheKey = $options['cache'] ? $this->cacheKeyFromRequest($options['key'], $resource, $data) : null; // Attempt to use the key to retrieve data. if ($cacheKey !== null) { $result = $this->service->cacheGet($cacheKey); } // If we don't have any data yet perform the request. if ($options['force'] || $result === null) { try { $result = $this->client->sendRequest($token, $resource, $method, $data, $headers, $options); } catch (Wolfnet_Api_ApiException $e) { /* If the exception states that the API Token is invalid we should remove it from the cache so that we retrieve a new one on the next request. */ if ($e->getCode() === Wolfnet_Api_Client::AUTH_ERROR) { $this->service->cacheDelete($this->cacheKeyFromApiKey($options['key'])); } throw $e; } // Now that we have the data set it in the cache if we have a key. if ($cacheKey !== null) { $this->service->cachePut($cacheKey, $result, self::CACHE_SPAN); } } else { $result['fromCache'] = true; } $result['cacheKey'] = $cacheKey; return $result; }