diff --git a/docs/configuration.md b/docs/configuration.md index 4bd34c0..d38688b 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -374,12 +374,13 @@ sensiolabs_gotenberg: user_agent: null # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers - extra_http_headers: + extra_http_headers: [] + + # Example: + # 'X-Custom-Header': 'custom-header-value' - # Prototype - name: - name: ~ - value: ~ + # Or the syntax below is also possible + # - { name: 'X-Custom-Header', value: 'custom-header-value' } # Return a 409 Conflict response if the HTTP status code from the main page is not acceptable. - default [499,599]. https://gotenberg.dev/docs/routes#invalid-http-status-codes-chromium fail_on_http_status_codes: @@ -472,15 +473,13 @@ sensiolabs_gotenberg: method: null # One of "POST"; "PUT"; "PATCH" # HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook - extra_http_headers: + extra_http_headers: [] # Example: - # - { name: X-Custom-Header, value: custom-header-value } - - # Prototype - name: - name: ~ - value: ~ + # 'X-Custom-Header': 'custom-header-value' + + # Or the syntax below is also possible + # - { name: 'X-Custom-Header', value: 'custom-header-value' } markdown: # Add default header to the builder. @@ -571,12 +570,13 @@ sensiolabs_gotenberg: user_agent: null # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers - extra_http_headers: + extra_http_headers: [] + + # Example: + # 'X-Custom-Header': 'custom-header-value' - # Prototype - name: - name: ~ - value: ~ + # Or the syntax below is also possible + # - { name: 'X-Custom-Header', value: 'custom-header-value' } # Return a 409 Conflict response if the HTTP status code from the main page is not acceptable. - default [499,599]. https://gotenberg.dev/docs/routes#invalid-http-status-codes-chromium fail_on_http_status_codes: @@ -669,15 +669,13 @@ sensiolabs_gotenberg: method: null # One of "POST"; "PUT"; "PATCH" # HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook - extra_http_headers: + extra_http_headers: [] # Example: - # - { name: X-Custom-Header, value: custom-header-value } - - # Prototype - name: - name: ~ - value: ~ + # 'X-Custom-Header': 'custom-header-value' + + # Or the syntax below is also possible + # - { name: 'X-Custom-Header', value: 'custom-header-value' } office: # Set the password for opening the source file. https://gotenberg.dev/docs/routes#page-properties-libreoffice @@ -907,12 +905,13 @@ sensiolabs_gotenberg: user_agent: null # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers - extra_http_headers: + extra_http_headers: [] + + # Example: + # 'X-Custom-Header': 'custom-header-value' - # Prototype - name: - name: ~ - value: ~ + # Or the syntax below is also possible + # - { name: 'X-Custom-Header', value: 'custom-header-value' } # Return a 409 Conflict response if the HTTP status code from the main page is not acceptable. - default [499,599]. https://gotenberg.dev/docs/routes#invalid-http-status-codes-chromium fail_on_http_status_codes: @@ -975,15 +974,13 @@ sensiolabs_gotenberg: method: null # One of "POST"; "PUT"; "PATCH" # HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook - extra_http_headers: + extra_http_headers: [] # Example: - # - { name: X-Custom-Header, value: custom-header-value } - - # Prototype - name: - name: ~ - value: ~ + # 'X-Custom-Header': 'custom-header-value' + + # Or the syntax below is also possible + # - { name: 'X-Custom-Header', value: 'custom-header-value' } url: # The device screen width in pixels. - default 800. https://gotenberg.dev/docs/routes#screenshots-route @@ -1035,12 +1032,13 @@ sensiolabs_gotenberg: user_agent: null # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers - extra_http_headers: + extra_http_headers: [] + + # Example: + # 'X-Custom-Header': 'custom-header-value' - # Prototype - name: - name: ~ - value: ~ + # Or the syntax below is also possible + # - { name: 'X-Custom-Header', value: 'custom-header-value' } # Return a 409 Conflict response if the HTTP status code from the main page is not acceptable. - default [499,599]. https://gotenberg.dev/docs/routes#invalid-http-status-codes-chromium fail_on_http_status_codes: @@ -1103,15 +1101,13 @@ sensiolabs_gotenberg: method: null # One of "POST"; "PUT"; "PATCH" # HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook - extra_http_headers: + extra_http_headers: [] # Example: - # - { name: X-Custom-Header, value: custom-header-value } - - # Prototype - name: - name: ~ - value: ~ + # 'X-Custom-Header': 'custom-header-value' + + # Or the syntax below is also possible + # - { name: 'X-Custom-Header', value: 'custom-header-value' } markdown: # The device screen width in pixels. - default 800. https://gotenberg.dev/docs/routes#screenshots-route @@ -1163,12 +1159,13 @@ sensiolabs_gotenberg: user_agent: null # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers - extra_http_headers: + extra_http_headers: [] - # Prototype - name: - name: ~ - value: ~ + # Example: + # 'X-Custom-Header': 'custom-header-value' + + # Or the syntax below is also possible + # - { name: 'X-Custom-Header', value: 'custom-header-value' } # Return a 409 Conflict response if the HTTP status code from the main page is not acceptable. - default [499,599]. https://gotenberg.dev/docs/routes#invalid-http-status-codes-chromium fail_on_http_status_codes: @@ -1231,15 +1228,13 @@ sensiolabs_gotenberg: method: null # One of "POST"; "PUT"; "PATCH" # HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook - extra_http_headers: + extra_http_headers: [] # Example: - # - { name: X-Custom-Header, value: custom-header-value } - - # Prototype - name: - name: ~ - value: ~ + # 'X-Custom-Header': 'custom-header-value' + + # Or the syntax below is also possible + # - { name: 'X-Custom-Header', value: 'custom-header-value' } ``` > [!TIP] @@ -1250,6 +1245,17 @@ sensiolabs_gotenberg: HTTP headers to send by Chromium while loading the HTML document. +```yaml +sensiolabs_gotenberg: + default_options: + pdf: + html: + extra_http_headers: + 'My-Header': 'MyValue' +``` + +Or the syntax below is also possible + ```yaml sensiolabs_gotenberg: default_options: @@ -1259,14 +1265,14 @@ sensiolabs_gotenberg: - { name: 'My-Header', value: 'MyValue' } ``` -Or Headers to send to your webhook endpoint +Headers to send to your webhook endpoint ```yaml sensiolabs_gotenberg: webhook: default: extra_http_headers: - - { name: 'My-Header', value: 'MyValue' } + 'My-Header': 'MyValue' ``` > [!TIP] diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index c8d5b30..485f0c2 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -321,7 +321,7 @@ private function addChromiumPdfOptionsNode(ArrayNodeDefinition $parent): void ->thenInvalid('Invalid value %s') ->end() ->end() - ->append($this->addExtraHttpHeaders()) + ->append($this->addExtraHttpHeadersNode()) ->arrayNode('fail_on_http_status_codes') ->info('Return a 409 Conflict response if the HTTP status code from the main page is not acceptable. - default [499,599]. https://gotenberg.dev/docs/routes#invalid-http-status-codes-chromium') ->defaultValue([499, 599]) @@ -346,8 +346,8 @@ private function addChromiumPdfOptionsNode(ArrayNodeDefinition $parent): void ->info('Do not wait for Chromium network to be idle. - default false. https://gotenberg.dev/docs/routes#performance-mode-chromium') ->defaultNull() ->end() - ->append($this->addPdfMetadata()) - ->append($this->addDownloadFrom()) + ->append($this->addPdfMetadataNode()) + ->append($this->addDownloadFromNode()) ->end() ->validate() ->ifTrue(function ($v): bool { @@ -357,7 +357,7 @@ private function addChromiumPdfOptionsNode(ArrayNodeDefinition $parent): void ->end() ; - $this->addPdfFormat($parent); + $this->addPdfFormatNode($parent); $this->addSplitConfigurationNode($parent); } @@ -456,7 +456,7 @@ private function addChromiumScreenshotOptionsNode(ArrayNodeDefinition $parent): ->thenInvalid('Invalid value %s') ->end() ->end() - ->append($this->addExtraHttpHeaders()) + ->append($this->addExtraHttpHeadersNode()) ->arrayNode('fail_on_http_status_codes') ->info('Return a 409 Conflict response if the HTTP status code from the main page is not acceptable. - default [499,599]. https://gotenberg.dev/docs/routes#invalid-http-status-codes-chromium') ->defaultValue([499, 599]) @@ -481,7 +481,7 @@ private function addChromiumScreenshotOptionsNode(ArrayNodeDefinition $parent): ->info('Do not wait for Chromium network to be idle. - default false. https://gotenberg.dev/docs/routes#performance-mode-chromium') ->defaultNull() ->end() - ->append($this->addDownloadFrom()) + ->append($this->addDownloadFromNode()) ->end() ; } @@ -523,7 +523,7 @@ private function addPdfOfficeNode(): NodeDefinition ->info('Merge alphanumerically the resulting PDFs. - default false. https://gotenberg.dev/docs/routes#merge-libreoffice') ->defaultNull() ->end() - ->append($this->addPdfMetadata()) + ->append($this->addPdfMetadataNode()) ->booleanNode('allow_duplicate_field_names') ->info('Specify whether multiple form fields exported are allowed to have the same field name. - default false. https://gotenberg.dev/docs/routes#page-properties-libreoffice') ->defaultNull() @@ -595,11 +595,11 @@ private function addPdfOfficeNode(): NodeDefinition ->values(array_map(static fn (ImageResolutionDPI $case): int => $case->value, ImageResolutionDPI::cases())) ->defaultNull() ->end() - ->append($this->addDownloadFrom()) + ->append($this->addDownloadFromNode()) ->end() ; - $this->addPdfFormat($treeBuilder->getRootNode()); + $this->addPdfFormatNode($treeBuilder->getRootNode()); $this->addSplitConfigurationNode($treeBuilder->getRootNode()); return $treeBuilder->getRootNode(); @@ -608,9 +608,9 @@ private function addPdfOfficeNode(): NodeDefinition private function addPdfConvertNode(): NodeDefinition { $treeBuilder = new TreeBuilder('convert'); - $this->addPdfFormat($treeBuilder->getRootNode()); + $this->addPdfFormatNode($treeBuilder->getRootNode()); $treeBuilder->getRootNode() - ->append($this->addDownloadFrom()) + ->append($this->addDownloadFromNode()) ->end(); return $treeBuilder->getRootNode(); @@ -619,10 +619,10 @@ private function addPdfConvertNode(): NodeDefinition private function addPdfMergeNode(): NodeDefinition { $treeBuilder = new TreeBuilder('merge'); - $this->addPdfFormat($treeBuilder->getRootNode()); + $this->addPdfFormatNode($treeBuilder->getRootNode()); $treeBuilder->getRootNode() - ->append($this->addPdfMetadata()) - ->append($this->addDownloadFrom()) + ->append($this->addPdfMetadataNode()) + ->append($this->addDownloadFromNode()) ->end(); return $treeBuilder->getRootNode(); @@ -636,7 +636,7 @@ private function addPdfSplitNode(): NodeDefinition return $treeBuilder->getRootNode(); } - private function addPdfFormat(ArrayNodeDefinition $parent): void + private function addPdfFormatNode(ArrayNodeDefinition $parent): void { $parent ->addDefaultsIfNotSet() @@ -654,7 +654,7 @@ private function addPdfFormat(ArrayNodeDefinition $parent): void ; } - private function addPdfMetadata(): NodeDefinition + private function addPdfMetadataNode(): NodeDefinition { $treeBuilder = new TreeBuilder('metadata'); @@ -696,30 +696,7 @@ private function addNamedWebhookDefinition(): NodeDefinition ->end() ->append($this->addWebhookConfigurationNode('success')) ->append($this->addWebhookConfigurationNode('error')) - ->arrayNode('extra_http_headers') - ->info('HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook') - ->useAttributeAsKey('name') - ->arrayPrototype() - ->children() - ->scalarNode('name') - ->validate() - ->ifTrue(static function ($option) { - return !\is_string($option); - }) - ->thenInvalid('Invalid header name %s') - ->end() - ->end() - ->scalarNode('value') - ->validate() - ->ifTrue(static function ($option) { - return !\is_string($option); - }) - ->thenInvalid('Invalid header value %s') - ->end() - ->end() - ->end() - ->end() - ->end() + ->append($this->addExtraHttpHeadersNode()) ->end() ->validate() ->ifTrue(static function (mixed $option): bool { @@ -748,33 +725,7 @@ private function addWebhookDeclarationNode(ArrayNodeDefinition $parent): void ->end() ->append($this->addWebhookConfigurationNode('success')) ->append($this->addWebhookConfigurationNode('error')) - ->arrayNode('extra_http_headers') - ->info('HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook') - ->example([ - ['name' => 'X-Custom-Header', 'value' => 'custom-header-value'], - ]) - ->useAttributeAsKey('name') - ->arrayPrototype() - ->children() - ->scalarNode('name') - ->validate() - ->ifTrue(static function ($option) { - return !\is_string($option); - }) - ->thenInvalid('Invalid header name %s') - ->end() - ->end() - ->scalarNode('value') - ->validate() - ->ifTrue(static function ($option) { - return !\is_string($option); - }) - ->thenInvalid('Invalid header value %s') - ->end() - ->end() - ->end() - ->end() - ->end() + ->append($this->addExtraHttpHeadersNode()) ->end() ->validate() ->ifTrue(static function ($option): bool { @@ -826,7 +777,7 @@ private function addWebhookConfigurationNode(string $name): NodeDefinition ; } - private function addDownloadFrom(): NodeDefinition + private function addDownloadFromNode(): NodeDefinition { $treeBuilder = new TreeBuilder('download_from'); @@ -864,33 +815,16 @@ private function addDownloadFrom(): NodeDefinition ; } - private function addExtraHttpHeaders(): NodeDefinition + private function addExtraHttpHeadersNode(): NodeDefinition { $treeBuilder = new TreeBuilder('extra_http_headers'); return $treeBuilder->getRootNode() ->info('HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers') ->defaultValue([]) + ->normalizeKeys(false) ->useAttributeAsKey('name') - ->arrayPrototype() - ->children() - ->scalarNode('name') - ->validate() - ->ifTrue(static function ($option): bool { - return !\is_string($option); - }) - ->thenInvalid('Invalid header name %s') - ->end() - ->end() - ->scalarNode('value') - ->validate() - ->ifTrue(static function ($option): bool { - return !\is_string($option); - }) - ->thenInvalid('Invalid header value %s') - ->end() - ->end() - ->end() + ->variablePrototype() ->end() ; } diff --git a/tests/DependencyInjection/ConfigurationTest.php b/tests/DependencyInjection/ConfigurationTest.php index 4fdefb9..1b6b7c2 100644 --- a/tests/DependencyInjection/ConfigurationTest.php +++ b/tests/DependencyInjection/ConfigurationTest.php @@ -60,7 +60,24 @@ public function testInvalidNativePageRange(mixed $range): void ); } - public function testWithExtraHeadersConfiguration(): void + /** + * @return iterable|list>> + */ + public static function provideExtraHeaderConfiguration(): iterable + { + yield 'with variable Prototype configuration' => [ + ['MyHeader' => 'MyValue', 'User-Agent' => 'MyAgent'], + ]; + yield 'with attribute as key configuration' => [ + [['name' => 'MyHeader', 'value' => 'MyValue'], ['name' => 'User-Agent', 'value' => 'MyAgent']], + ]; + } + + /** + * @param list|list> $configuration + */ + #[DataProvider('provideExtraHeaderConfiguration')] + public function testWithExtraHeadersConfiguration(array $configuration): void { $processor = new Processor(); /** @var array{'default_options': array} $config */ @@ -69,7 +86,7 @@ public function testWithExtraHeadersConfiguration(): void 'http_client' => 'http_client', 'default_options' => [ 'pdf' => [ - 'html' => ['extra_http_headers' => [['name' => 'MyHeader', 'value' => 'MyValue'], ['name' => 'User-Agent', 'value' => 'MyValue']]], + 'html' => ['extra_http_headers' => $configuration], ], ], ], @@ -77,7 +94,7 @@ public function testWithExtraHeadersConfiguration(): void $config = $this->cleanOptions($config['default_options']['pdf']['html']); self::assertEquals([ - 'extra_http_headers' => ['MyHeader' => 'MyValue', 'User-Agent' => 'MyValue'], + 'extra_http_headers' => ['MyHeader' => 'MyValue', 'User-Agent' => 'MyAgent'], 'fail_on_http_status_codes' => ['499', '599'], ], $config); } diff --git a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php index d984c61..d649438 100644 --- a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php +++ b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php @@ -604,7 +604,7 @@ private static function getValidConfig(): array 'httpOnly' => true, 'sameSite' => 'Lax', ]], - 'extra_http_headers' => [['name' => 'MyHeader', 'value' => 'MyValue'], ['name' => 'User-Agent', 'value' => 'MyValue']], + 'extra_http_headers' => ['MyHeader' => 'MyValue', 'User-Agent' => 'MyValue'], 'fail_on_http_status_codes' => [401], 'fail_on_resource_http_status_codes' => [401], 'fail_on_resource_loading_failed' => true, @@ -631,7 +631,7 @@ private static function getValidConfig(): array 'wait_delay' => '5s', 'wait_for_expression' => 'window.globalVar === "ready"', 'emulated_media_type' => 'screen', - 'extra_http_headers' => [['name' => 'MyHeader', 'value' => 'MyValue'], ['name' => 'User-Agent', 'value' => 'MyValue']], + 'extra_http_headers' => ['MyHeader' => 'MyValue', 'User-Agent' => 'MyValue'], 'fail_on_http_status_codes' => [401, 403], 'fail_on_resource_http_status_codes' => [401, 403], 'fail_on_resource_loading_failed' => false, @@ -658,7 +658,7 @@ private static function getValidConfig(): array 'wait_delay' => '10s', 'wait_for_expression' => 'window.globalVar === "ready"', 'emulated_media_type' => 'screen', - 'extra_http_headers' => [['name' => 'MyHeader', 'value' => 'MyValue'], ['name' => 'User-Agent', 'value' => 'MyValue']], + 'extra_http_headers' => ['MyHeader' => 'MyValue', 'User-Agent' => 'MyValue'], 'fail_on_http_status_codes' => [404], 'fail_on_resource_http_status_codes' => [404], 'fail_on_resource_loading_failed' => false, @@ -701,7 +701,7 @@ private static function getValidConfig(): array 'secure' => true, 'httpOnly' => true, ]], - 'extra_http_headers' => [['name' => 'MyHeader', 'value' => 'MyValue'], ['name' => 'User-Agent', 'value' => 'MyValue']], + 'extra_http_headers' => ['MyHeader' => 'MyValue', 'User-Agent' => 'MyValue'], 'fail_on_http_status_codes' => [401], 'fail_on_resource_http_status_codes' => [401], 'fail_on_resource_loading_failed' => true, @@ -724,7 +724,7 @@ private static function getValidConfig(): array 'value' => 'sensio', 'domain' => 'sensiolabs.com', ]], - 'extra_http_headers' => [['name' => 'MyHeader', 'value' => 'MyValue'], ['name' => 'User-Agent', 'value' => 'MyValue']], + 'extra_http_headers' => ['MyHeader' => 'MyValue', 'User-Agent' => 'MyValue'], 'fail_on_http_status_codes' => [401, 403], 'fail_on_resource_http_status_codes' => [401, 403], 'fail_on_resource_loading_failed' => false, @@ -746,7 +746,7 @@ private static function getValidConfig(): array 'value' => 'sensio', 'domain' => 'sensiolabs.com', ]], - 'extra_http_headers' => [['name' => 'MyHeader', 'value' => 'MyValue'], ['name' => 'User-Agent', 'value' => 'MyValue']], + 'extra_http_headers' => ['MyHeader' => 'MyValue', 'User-Agent' => 'MyValue'], 'fail_on_http_status_codes' => [401, 403], 'fail_on_resource_http_status_codes' => [401, 403], 'fail_on_resource_loading_failed' => false,