diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 88e0a071..744eb5a4 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -22,16 +22,13 @@ jobs: include: # Minimum supported Symfony version and lowest PHP version - dependencies: "php-http/guzzle7-adapter php-http/discovery:^1.12" - php-version: "7.3" + php-version: "7.4" dependency-versions: "lowest" symfony-deprecations-helper: "weak" stability: "stable" # Test the latest stable release - dependencies: "php-http/guzzle7-adapter php-http/vcr-plugin:^1.0@dev" - php-version: "7.3" - symfony-deprecations-helper: "weak" - - dependencies: "php-http/guzzle6-adapter" php-version: "7.4" symfony-deprecations-helper: "weak" - dependencies: "php-http/guzzle7-adapter" @@ -49,7 +46,7 @@ jobs: # Test with httplug 2.x clients - dependencies: "php-http/guzzle7-adapter php-http/curl-client:^2.0.0 php-http/vcr-plugin:^1.0@dev php-http/socket-client:^2.0" - php-version: "7.3" + php-version: "7.4" symfony-deprecations-helper: "weak" # Latest commit to master @@ -65,7 +62,7 @@ jobs: # Test maintained versions of Symfony - dependencies: "php-http/guzzle7-adapter symfony/http-client:^5.4" symfony-require: "5.4.*" - php-version: "7.3" + php-version: "7.4" symfony-deprecations-helper: "weak" - dependencies: "php-http/guzzle7-adapter symfony/http-client:^6.0" symfony-require: "6.3.*" @@ -78,7 +75,7 @@ jobs: steps: - name: "Checkout" - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" with: fetch-depth: 2 @@ -88,6 +85,7 @@ jobs: php-version: "${{ matrix.php-version }}" coverage: "pcov" ini-values: "zend.assertions=1" + tools: "flex" - name: "Enforce using stable dependencies" run: "composer config minimum-stability stable" @@ -95,11 +93,10 @@ jobs: - name: "Add dependencies and enable flex" run: | - composer require --no-update symfony/flex ${{ matrix.dependencies }} - composer config --no-plugins allow-plugins.symfony/flex true + composer require --no-update ${{ matrix.dependencies }} - name: "Install dependencies with Composer" - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: dependency-versions: "${{ matrix.dependency-versions }}" composer-options: "${{ matrix.composer-options }}" diff --git a/.github/workflows/php-cs-fixer.yml b/.github/workflows/php-cs-fixer.yml index d4c0b0be..4e50e693 100644 --- a/.github/workflows/php-cs-fixer.yml +++ b/.github/workflows/php-cs-fixer.yml @@ -15,7 +15,7 @@ jobs: steps: - name: "Checkout" - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" - name: "PHP-CS-Fixer" uses: "docker://oskarstark/php-cs-fixer-ga:2.19.0" with: diff --git a/CHANGELOG.md b/CHANGELOG.md index e241c748..013644ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,18 @@ The change log describes what is "Added", "Removed", "Changed" or "Fixed" betwee # Version 1 +# 1.34.1 - 2024-09-01 + +- The rate-limiter name in the throttle plugin configuration is required. + +# 1.34.0 - 2024-06-17 + +- Support to configure the throttle plugin. + +# 1.33.1 - 2024-05-27 + +- Fixed extension to depend on the DependencyInjection component rather than the HttpKernel. + # 1.33.0 - 2024-02-27 - Support php-http/cache-plugin 2.0 and bump minimal version to 1.7 by defaulting the stream factory for cache to `httplug.psr17_stream_factory` (#448). diff --git a/composer.json b/composer.json index bab75c8f..1531180a 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ } ], "require": { - "php": "^7.3 || ^8.0", + "php": "^7.4 || ^8.0", "php-http/client-common": "^2.0", "php-http/client-implementation": "^1.0", "php-http/discovery": "^1.14", @@ -42,21 +42,25 @@ "symfony/options-resolver": "^5.4 || ^6.0 || ^7.0" }, "conflict": { + "kriswallsmith/buzz": "<0.17", "php-http/guzzle6-adapter": "<1.1", "php-http/cache-plugin": "<1.7", "php-http/curl-client": "<2.0", "php-http/socket-client": "<2.0", - "kriswallsmith/buzz": "<0.17", - "php-http/react-adapter": "<3.0" + "php-http/react-adapter": "<3.0", + "php-http/throttle-plugin": "<1.1" }, "require-dev": { "guzzlehttp/psr7": "^1.7 || ^2.0", - "matthiasnoback/symfony-dependency-injection-test": "^4.0 || ^5.0", + "matthiasnoback/symfony-config-test": "^4.3 || ^5.0", + "matthiasnoback/symfony-dependency-injection-test": "^4.3.1 || ^5.0", "nyholm/nsa": "^1.1", "nyholm/psr7": "^1.2.1", "php-http/cache-plugin": "^1.7", + "php-http/throttle-plugin": "^1.1", "php-http/mock-client": "^1.2", "php-http/promise": "^1.0", + "phpunit/phpunit": "^9.6", "symfony/browser-kit": "^5.4 || ^6.0 || ^7.0", "symfony/cache": "^5.4 || ^6.0 || ^7.0", "symfony/dom-crawler": "^5.4 || ^6.0 || ^7.0", @@ -95,7 +99,7 @@ }, "prefer-stable": false, "scripts": { - "test": "vendor/bin/simple-phpunit", - "test-ci": "vendor/bin/simple-phpunit --coverage-text --coverage-clover=build/coverage.xml" + "test": "vendor/bin/phpunit", + "test-ci": "vendor/bin/phpunit --coverage-text --coverage-clover=build/coverage.xml" } } diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 217a825e..f25b0bb0 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -611,7 +611,7 @@ private function addSharedPluginNodes(ArrayNodeDefinition $pluginNode, $disableA ->end(); // End stopwatch plugin - $error = $children->arrayNode('error') + $children->arrayNode('error') ->canBeEnabled() ->addDefaultsIfNotSet() ->children() @@ -619,6 +619,21 @@ private function addSharedPluginNodes(ArrayNodeDefinition $pluginNode, $disableA ->end() ->end(); // End error plugin + + $children->arrayNode('throttle') + ->canBeEnabled() + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('name') + ->info('The name of the configured symfony/rate-limiter to use') + ->isRequired() + ->end() + ->scalarNode('key')->defaultNull()->end() + ->integerNode('tokens')->defaultValue(1)->end() + ->floatNode('max_time')->defaultNull()->end() + ->end() + ->end(); + // End throttle plugin } /** diff --git a/src/DependencyInjection/HttplugExtension.php b/src/DependencyInjection/HttplugExtension.php index 3807f95b..639b3fe4 100644 --- a/src/DependencyInjection/HttplugExtension.php +++ b/src/DependencyInjection/HttplugExtension.php @@ -10,6 +10,7 @@ use Http\Client\Common\HttpMethodsClient; use Http\Client\Common\HttpMethodsClientInterface; use Http\Client\Common\Plugin\AuthenticationPlugin; +use Http\Client\Common\Plugin\ThrottlePlugin; use Http\Client\Common\PluginClient; use Http\Client\Common\PluginClientFactory; use Http\Client\HttpAsyncClient; @@ -30,9 +31,10 @@ use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\HttpKernel\DependencyInjection\Extension; +use Symfony\Component\RateLimiter\LimiterInterface; use Twig\Environment as TwigEnvironment; /** @@ -284,6 +286,23 @@ private function configurePluginByName($name, Definition $definition, array $con break; + case 'throttle': + if (!\class_exists(ThrottlePlugin::class)) { + throw new InvalidConfigurationException('You need to require the Throttle Plugin to be able to use it: "composer require php-http/throttle-plugin".'); + } + + $container + ->register($serviceId.$config['name'], LimiterInterface::class) + ->setFactory([new Reference('limiter.'.$config['name']), 'create']) + ->addArgument($config['key']) + ->setPublic(false); + + $definition->replaceArgument(0, new Reference($serviceId.$config['name'])); + $definition->setArgument('$tokens', $config['tokens']); + $definition->setArgument('$maxTime', $config['max_time']); + + break; + /* client specific plugins */ case 'add_host': diff --git a/src/Resources/config/plugins.xml b/src/Resources/config/plugins.xml index 749407c4..9f9c0ec1 100644 --- a/src/Resources/config/plugins.xml +++ b/src/Resources/config/plugins.xml @@ -28,6 +28,9 @@ + + + diff --git a/tests/Unit/DependencyInjection/ConfigurationTest.php b/tests/Unit/DependencyInjection/ConfigurationTest.php index e566bfdb..981a4810 100644 --- a/tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/tests/Unit/DependencyInjection/ConfigurationTest.php @@ -89,6 +89,12 @@ class ConfigurationTest extends AbstractExtensionConfigurationTestCase 'enabled' => false, 'only_server_exception' => false, ], + 'throttle' => [ + 'enabled' => false, + 'key' => null, + 'tokens' => 1, + 'max_time' => null, + ], ], 'discovery' => [ 'client' => 'auto', @@ -293,6 +299,12 @@ public function testSupportsAllConfigFormats(): void 'enabled' => false, 'only_server_exception' => false, ], + 'throttle' => [ + 'enabled' => false, + 'key' => null, + 'tokens' => 1, + 'max_time' => null, + ], ], 'discovery' => [ 'client' => 'auto', diff --git a/tests/Unit/DependencyInjection/HttplugExtensionTest.php b/tests/Unit/DependencyInjection/HttplugExtensionTest.php index b2895062..08925375 100644 --- a/tests/Unit/DependencyInjection/HttplugExtensionTest.php +++ b/tests/Unit/DependencyInjection/HttplugExtensionTest.php @@ -131,6 +131,11 @@ public function testClientPlugins(): void 'headers' => ['X-FOO'], ], ], + [ + 'query_defaults' => [ + 'parameters' => ['locale' => 'en'], + ], + ], [ 'request_seekable_body' => [ 'use_file_buffer' => true, @@ -140,8 +145,8 @@ public function testClientPlugins(): void 'response_seekable_body' => true, ], [ - 'query_defaults' => [ - 'parameters' => ['locale' => 'en'], + 'throttle' => [ + 'name' => 'test', ], ], [ @@ -179,9 +184,10 @@ public function testClientPlugins(): void 'httplug.client.acme.plugin.header_defaults', 'httplug.client.acme.plugin.header_set', 'httplug.client.acme.plugin.header_remove', + 'httplug.client.acme.plugin.query_defaults', 'httplug.client.acme.plugin.request_seekable_body', 'httplug.client.acme.plugin.response_seekable_body', - 'httplug.client.acme.plugin.query_defaults', + 'httplug.client.acme.plugin.throttle', 'httplug.client.acme.authentication.my_basic', 'httplug.client.acme.plugin.cache', 'httplug.client.acme.plugin.error',