Source of file OAuthClient.php
Size: 10,781 Bytes - Last Modified: 2019-08-09T18:27:54+00:00
/home/travis/build/zerospam/sdk-framework/src/Client/OAuthClient.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 | <?php /** * Created by PhpStorm. * User: aaflalo * Date: 18-06-01 * Time: 09:42. */ namespace ZEROSPAM\Framework\SDK\Client; use GuzzleHttp\Client; use GuzzleHttp\ClientInterface; use GuzzleHttp\Exception\BadResponseException; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\RequestOptions; use League\OAuth2\Client\Token\AccessToken; use Psr\Http\Message\ResponseInterface; use ZEROSPAM\Framework\SDK\Client\Exception\SDKException; use ZEROSPAM\Framework\SDK\Client\Exception\TooManyRetriesException; use ZEROSPAM\Framework\SDK\Client\Middleware\IMiddleware; use ZEROSPAM\Framework\SDK\Client\Middleware\IPreRequestMiddleware; use ZEROSPAM\Framework\SDK\Client\Middleware\IRefreshTokenMiddleware; use ZEROSPAM\Framework\SDK\Config\IOAuthConfiguration; use ZEROSPAM\Framework\SDK\Exception\Middleware\NoMiddlewareSetException; use ZEROSPAM\Framework\SDK\Request\Api\IRequest; use ZEROSPAM\Framework\SDK\Request\Type\RequestType; use ZEROSPAM\Framework\SDK\Response\Api\BaseResponse; use ZEROSPAM\Framework\SDK\Response\Api\IRateLimitedResponse; use ZEROSPAM\Framework\SDK\Response\Api\IResponse; use ZEROSPAM\Framework\SDK\Response\RateLimit\RateLimitData; use ZEROSPAM\Framework\SDK\Utils\JSON\JSONParsing; /** * Class OAuthClient * * Client for OAuth server interaction * * @package ZEROSPAM\Framework\SDK\Client */ class OAuthClient implements IOAuthClient { /** * @var IOAuthConfiguration */ private $configuration; /** * @var RateLimitData */ private $rateLimit; /** * @var ClientInterface */ private $guzzleClient; /** * @var AccessToken */ private $token; /** * @var \ZEROSPAM\Framework\SDK\Client\Middleware\IMiddleware[][] */ private $postRequestMiddlewares = []; /** * @var IPreRequestMiddleware[] */ private $preRequestMiddlewares = []; /** * @var IRefreshTokenMiddleware[] */ private $refreshTokenMiddlewares = []; /** * @var IRequest */ private $lastRequest; /** * OauthClient constructor. * * @param IOAuthConfiguration $configuration * @param AccessToken $token * @param ClientInterface|null $guzzleClient Only set if you want to override the default client */ public function __construct(IOAuthConfiguration $configuration, AccessToken $token, ClientInterface $guzzleClient = null) { $this->configuration = $configuration; $this->rateLimit = new RateLimitData(); $this->token = $token; $this->guzzleClient = $guzzleClient; if ($this->guzzleClient == null) { $this->guzzleClient = new Client(['base_uri' => $this->configuration->getEndPoint()]); } foreach ($this->configuration->defaultMiddlewares() as $middleware) { $this->registerMiddleware($middleware); } foreach ($this->configuration->defaultPreRequestMiddlewares() as $middleware) { $this->registerPreRequestMiddleware($middleware); } } /** * Register the given middleware. * * @param \ZEROSPAM\Framework\SDK\Client\Middleware\IMiddleware $middleware * * @return IOAuthClient */ public function registerMiddleware(IMiddleware $middleware): IOAuthClient { $middleware->setClient($this); foreach ($middleware::statusCode() as $statusCode) { $this->postRequestMiddlewares[$statusCode][] = $middleware; } return $this; } /** * Register a pre request middleware * * @param IPreRequestMiddleware $middleware * * @return IOAuthClient */ public function registerPreRequestMiddleware(IPreRequestMiddleware $middleware): IOAuthClient { $this->preRequestMiddlewares[get_class($middleware)] = $middleware; return $this; } /** * Register a middleware to take care of refresh token * * @param IRefreshTokenMiddleware $middleware * * @return IOAuthClient */ public function registerRefreshTokenMiddleware(IRefreshTokenMiddleware $middleware): IOAuthClient { $middleware->setClient($this); $this->refreshTokenMiddlewares[get_class($middleware)] = $middleware; return $this; } /** * Unregister the middleware. * * In fact, all middleware having the same class * * @param \ZEROSPAM\Framework\SDK\Client\Middleware\IMiddleware $middleware * * @return IOAuthClient */ public function unregisterMiddleware(IMiddleware $middleware): IOAuthClient { $middlewareClass = get_class($middleware); foreach ($middleware::statusCode() as $statusCode) { if (!isset($this->postRequestMiddlewares[$statusCode])) { continue; } $result = array_filter( $this->postRequestMiddlewares[$statusCode], function (IMiddleware $currMiddleware) use ($middlewareClass) { return get_class($currMiddleware) != $middlewareClass; } ); if (empty($result)) { unset($this->postRequestMiddlewares[$statusCode]); } else { $this->postRequestMiddlewares[$statusCode] = $result; } } return $this; } /** * UnRegister a pre request middleware * * @param IPreRequestMiddleware $middleware * * @return IOAuthClient */ public function unregisterPreRequestMiddleware(IPreRequestMiddleware $middleware): IOAuthClient { unset($this->preRequestMiddlewares[get_class($middleware)]); return $this; } /** * UnRegister a refreshToken middleware * * @param IRefreshTokenMiddleware $middleware * * @return IOAuthClient */ public function unregisterRefreshTokenMiddleware(IRefreshTokenMiddleware $middleware): IOAuthClient { unset($this->refreshTokenMiddlewares[get_class($middleware)]); return $this; } /** * Refresh token. * * @throws NoMiddlewareSetException */ public function refreshToken(): AccessToken { if (empty($this->refreshTokenMiddlewares)) { throw new NoMiddlewareSetException('No refresh token middleware present.'); } $token = $this->token; foreach ($this->refreshTokenMiddlewares as $middleware) { $token = $middleware->handleRefreshToken($token, $this->lastRequest->tries()); } return $this->token = $token; } /** * Currently used access token. * * @return AccessToken */ public function getToken(): AccessToken { return $this->token; } /** * Set the AccessToken * * @param AccessToken $token */ public function setToken(AccessToken $token): void { $this->token = $token; } /** * Get linked configuration * * @return IOAuthConfiguration */ public function getConfiguration(): IOAuthConfiguration { return $this->configuration; } /** * Process the given request and return an array containing the results. * * @param IRequest $request * * @return IResponse */ public function processRequest(IRequest $request): IResponse { $this->lastRequest = $request; foreach ($this->preRequestMiddlewares as $middleware) { $middleware->handle($request); } $request->incrementTries(); $headers = $this->configuration->getProvider()->getHeaders($this->token); $options = $request->requestOptions(); if (isset($options[RequestOptions::HEADERS])) { $options[RequestOptions::HEADERS] = array_merge($options[RequestOptions::HEADERS], $headers); } else { $options[RequestOptions::HEADERS] = $headers; } try { $response = $this->guzzleClient->request($request->httpType()->getValue(), $request->toUri(), $options); $parsedData = JSONParsing::responseToJson($response); if (isset($this->postRequestMiddlewares[$response->getStatusCode()])) { foreach ($this->postRequestMiddlewares[$response->getStatusCode()] as $middleware) { $parsedData = $middleware->handle($request, $response, $parsedData); } } } catch (BadResponseException $e) { /** * Check status code. */ $response = $e->getResponse(); $this->processThrottleData($response); if (!isset($this->postRequestMiddlewares[$response->getStatusCode()])) { throw new SDKException($e->getMessage(), $e->getCode(), $e); } $parsedData = JSONParsing::responseToJson($response); foreach ($this->postRequestMiddlewares[$response->getStatusCode()] as $middleware) { $parsedData = $middleware->handle($request, $response, $parsedData); } } catch (RequestException $e) { if ($request->requestType()->is(RequestType::HTTP_GET()) && $request->tries() < 3) { return $this->processRequest($request); } throw new TooManyRetriesException($e->getMessage(), $e->getCode(), $e); } catch (\GuzzleHttp\Exception\GuzzleException $e) { throw new SDKException($e->getMessage(), $e->getCode(), $e); } /** * @var $data BaseResponse */ $data = $request->processResponse($parsedData); if ($data instanceof BaseResponse) { $data->setRawData($parsedData); } if ($data instanceof IRateLimitedResponse) { $this->processThrottleData($response); $data->setRateLimit($this->rateLimit); } $request->setResponse($data); return $data; } /** * Process the rate limit. * * @param ResponseInterface $response */ private function processThrottleData(ResponseInterface $response) { if (empty($rateLimit = $response->getHeader('X-RateLimit-Limit'))) { return; } if (empty($remaining = $response->getHeader('X-RateLimit-Remaining'))) { return; } if (!empty($reset = $response->getHeader('X-RateLimit-Reset'))) { $this->rateLimit->setEndOfThrottle(intval($reset[0])); } else { $this->rateLimit->setEndOfThrottle(null); } $this->rateLimit->setMaxPerMinute(intval($rateLimit[0]))->setRemaining(intval($remaining[0])); } } |