From 8ffb3c25dd7e5e678e521d784ef915450e5d115e Mon Sep 17 00:00:00 2001 From: evgeek Date: Fri, 10 Dec 2021 16:47:00 +0300 Subject: [PATCH] Made the SDK Client immutable --- README.md | 76 +++++++-------------- src/Client.php | 180 +++++++++---------------------------------------- 2 files changed, 54 insertions(+), 202 deletions(-) diff --git a/README.md b/README.md index f4f7355..fd32839 100644 --- a/README.md +++ b/README.md @@ -24,13 +24,6 @@ require '/path/to/you/vendor/autoload.php'; //Create and configure a new SDK client $sdk = new Client('YOU_TOKEN'); -//Setup ScraperAPI parameters according to the documentation -$sdk - ->setCountryCode('us') - ->setDeviceType('desktop') - ->setKeepHeaders(true) - ->addHeader('Accept', 'application/json'); - //Send request $response = $sdk->get('https://example.com'); @@ -43,6 +36,8 @@ echo $response->getBody()->getContents(); The client is configured through the constructor parameters: * ```$apiKey``` (required) - your API key from [ScraperAPI dashboard](https://dashboard.scraperapi.com/dashboard). +* ```$defaultApiParams``` - default API parameters for requests +* ```$defaultHeaders``` - default HTTP headers * ```$timeout``` (default ```60```) - request timeout. * ```$tries``` (default ```3```) - number of request attempts. * ```$delayMultiplier``` (default ```1```) - delay multiplier before new request attempt in seconds. Multiplier 3 means @@ -61,56 +56,33 @@ The client is configured through the constructor parameters: ### API parameters Configuring default API functionality according to [ScraperAPI documentation](https://www.scraperapi.com/documentation/) -. The default settings apply to all requests, unless they are overridden at the request level. All parameters are set -using fluent setters: +. The default settings apply to all requests, unless they are overridden at the request level. You can set the default +options only from constructor (SDK client is immutable), using the second parameter: ```php -$sdk - ->setCountryCode('us') //activate country geotargetting - ->setRender(true) //activate javascript rendering - ->setPremium(false) //activate premium residential and mobile IPs - ->setSessionNumber(123) //reuse the same proxy - ->setKeepHeaders(true) //use your own custom headers - ->setDeviceType('mobile') //set mobile or desktop user agents - ->setAutoparse(false); //activate auto parsing for select websites -``` - -Or you can set all parameters in single ```setParams()``` method using an array. This method erases all previously set -parameters. - -```php -$sdk->setParams([ - 'country_code' => 'us', - 'render' => true, - 'premium' => false, - 'session_number' => 123, - 'keep_headers' => true, - 'device_type' => 'mobile', - 'autoparse' => 'false', -]); +$defaultApiParams = [ + 'country_code' => 'us', //activate country geotargetting + 'render' => true, //activate javascript rendering + 'premium' => false, //activate premium residential and mobile IPs + 'session_number' => 123, //reuse the same proxy + 'keep_headers' => true, //use your own custom headers + 'device_type' => 'mobile', //set mobile or desktop user agents + 'autoparse' => 'false', //activate auto parsing for select websites +]; +$sdk = new Client('YOU_TOKEN', $defaultApiParams); ``` ### Headers -You can add default headers by ```addHeader()``` method. Don't forget to enable ```keep_headers``` to allow your headers -to be used! +You can add default headers with the third parameter of the constructor. Don't forget to enable ```keep_headers``` to +allow your headers to be used! ```php -$sdk - ->setKeepHeaders(true) - ->addHeader('Referer', 'https://example.com/') - ->addHeader('Accept', 'application/json'); -``` - -Or set headers in one step by ```setHeaders()``` method. This method erases all previously set headers. - -```php -$sdk - ->setKeepHeaders(true) - ->setHeaders([ - 'Referer' => 'https://example.com/', - 'Accept' => 'application/json', - ]); +$defaultHeaders = [ + 'Referer' => 'https://example.com/', + 'Accept' => 'application/json', +]; +$sdk = new Client('YOU_TOKEN', ['keep_headers' => true], $defaultHeaders); ``` ## Requests @@ -118,10 +90,10 @@ $sdk SDK supports ```GET```, ```POST``` and ```PUT``` HTTP methods. Standard parameters of each request methods: 1. ```$url``` (required) - url of scrapped resource. -2. ```$apiParams``` (default ```null```) - to set the API settings for the request. They will override the defaults set - in the SDK Client object (only those that overlap). +2. ```$apiParams``` (default ```null```) - to set the API settings for the request. They will override the defaults from + the SDK Client (only those that overlap). 3. ```$headers``` (default ```null```) - to set headers for the request. Just like ```$apiParams```, they will override - the defaults set in the SDK Client object (only those that overlap). + the defaults from the SDK Client (only those that overlap). ### Synchronous diff --git a/src/Client.php b/src/Client.php index f9f175f..b496894 100644 --- a/src/Client.php +++ b/src/Client.php @@ -18,14 +18,6 @@ /** * ScraperAPI documentation - https://www.scraperapi.com/documentation/ - * - * @method Client setCountryCode($value) Activate country geotargetting ('us' for example) - * @method Client setRender($value) Activate javascript rendering (true/false) - * @method Client setPremium($value) Activate premium residential and mobile IPs (true/false) - * @method Client setSessionNumber($value) Reuse the same proxy (123 for example) - * @method Client setKeepHeaders($value) Use your own custom headers (true/false) - * @method Client setDeviceType($value) Set your requests to use mobile or desktop user agents (desktop/mobile) - * @method Client setAutoparse($value) Activate auto parsing for select websites (true/false) */ class Client { @@ -33,44 +25,36 @@ class Client * ScraperAPI endpoint url */ private const API = 'https://api.scraperapi.com'; - - /** - * ScraperAPI available query params - */ - private const PARAMS_LIST = [ - 'country_code', - 'render', - 'premium', - 'session_number', - 'keep_headers', - 'device_type', - 'autoparse' - ]; - /** * ScraperAPI API key * @var string */ private $apiKey; - + /** + * ScraperAPI default request params + * @var array + */ + private $defaultApiParams; + /** + * Default headers + * @var array + */ + private $defaultHeaders; /** * If true, debug statement sent to the output. Useful for debugging async requests * @var bool */ private $printDebugInfo; - /** * If false, API key in debug statement will be replaced by 'API_KEY' string * @var bool */ private $showApiKey; - /** * Guzzle client * @var Guzzle */ private $guzzle; - /** * Optional PSR-3 logger for debug * @var LoggerInterface|null @@ -81,19 +65,6 @@ class Client * @var mixed */ private $logLevel; - - /** - * ScraperAPI default request params - * @var array - */ - private $params = []; - - /** - * Default headers - * @var array - */ - private $headers = []; - /** * Total promises in a bunch (for debug statements) * @var int @@ -105,13 +76,12 @@ class Client */ private $fulfilledPromises = 0; - /** @var array */ - private $paramsList; - /** * ScraperAPI documentation - https://www.scraperapi.com/documentation/ * * @param string $apiKey ScraperAPI API key + * @param array|null $defaultApiParams Default api parameters for requests + * @param array|null $defaultHeaders Default headers for requests * @param int $timeout Request timeout * @param int $tries Number of request attempts * @param int $delayMultiplier Delay multiplier before new request attempt in seconds @@ -123,6 +93,8 @@ class Client */ public function __construct( string $apiKey, + ?array $defaultApiParams = [], + ?array $defaultHeaders = [], int $timeout = 60, int $tries = 3, int $delayMultiplier = 1, @@ -134,13 +106,25 @@ public function __construct( ) { $this->apiKey = $apiKey; + $this->defaultApiParams = $defaultApiParams ?? []; + $this->defaultHeaders = $defaultHeaders ?? []; $this->printDebugInfo = $printDebugInfo; $this->showApiKey = $showApiKey; $this->logger = $logger; $this->logLevel = $logLevel; - $this->paramsList = array_flip(static::PARAMS_LIST); + $this->guzzle = $this->createGuzzleClient($timeout, $tries, $delayMultiplier, $maxExceptionsLength); + } + /** + * @param int $timeout + * @param int $tries + * @param int $delayMultiplier + * @param int $maxExceptionsLength + * @return Guzzle + */ + private function createGuzzleClient(int $timeout, int $tries, int $delayMultiplier, int $maxExceptionsLength): Guzzle + { $handlerStack = HandlerStack::create(); $handlerStack->push(Middleware::retry( function ( @@ -176,113 +160,9 @@ function ($try) use ($delayMultiplier) { )); $handlerStack->push(Middleware::httpErrors(new BodySummarizer($maxExceptionsLength)), 'http_errors'); - $this->guzzle = new Guzzle(['base_uri' => static::API, 'timeout' => $timeout, 'handler' => $handlerStack]); - } - - - /** - * Caller for Client default query params setters - * - * @param string $name - * @param array $arguments - * @return $this - * @throws Exception - */ - public function __call(string $name, array $arguments) - { - - if (strpos($name, 'set') === 0) { - $this->setter($name, $arguments); - return $this; - } - - throw new Exception("Unknown method '$name'."); + return new Guzzle(['base_uri' => static::API, 'timeout' => $timeout, 'handler' => $handlerStack]); } - /** - * @param string $name - * @param array $arguments - */ - private function setter(string $name, array $arguments): void - { - $paramName = $this->parseParamName($name); - if (array_key_exists($paramName, $this->paramsList)) { - $this->setParam($paramName, $arguments); - } - } - - /** - * @param string $name - * @param array $arguments - */ - private function setParam(string $name, array $arguments): void - { - $paramValue = $arguments[0] ?? null; - if ((!is_string($paramValue) && !is_bool($paramValue))) { - $paramValue = (string)$paramValue; - } - if (is_bool($paramValue)) { - $paramValue = $paramValue ? 'true' : 'false'; - } - $this->params[$name] = $paramValue; - } - - /** - * @param string $name - * @return string - */ - private function parseParamName(string $name): string - { - $words = preg_split('/(?=[A-Z])/', substr($name, 3)); - if (!$words) { - return ''; - } - - return (string)array_reduce($words, static function ($carry, $item) { - if ($item === '') { - return $carry; - } - return ($carry === '' || $carry === null) ? strtolower($item) : "{$carry}_" . strtolower($item); - }); - - } - - /** - * Set Client default query params in one step from array, replacing existing ones - * - * @param array $params - * @return Client - */ - public function setParams(array $params): Client - { - $this->params = $params; - return $this; - } - - /** - * Add default header to Client - * @param string $header - * @param array|string $value - * @return $this - */ - public function addHeader(string $header, $value): Client - { - $this->headers[$header] = $value; - return $this; - } - - /** - * Set default Client headers in one step from array, replacing existing ones - * @param array $headers - * @return $this - */ - public function setHeaders(array $headers): Client - { - $this->headers = $headers; - return $this; - } - - /** * Get info about ScraperAPI account * @@ -415,14 +295,14 @@ private function prepareQueryParams( ?array $json ): array { - $params = $this->params; + $params = $this->defaultApiParams; if (is_array($apiParams)) { foreach ($apiParams as $param => $value) { $params[$param] = $value; } } - $resultHeaders = $this->headers; + $resultHeaders = $this->defaultHeaders; if (is_array($headers)) { foreach ($headers as $param => $value) { $resultHeaders[$param] = $value;