Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Async generation #84

Merged
merged 26 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9915a29
Add ability to generate asynchronously using webhooks
maelanleborgne Jun 19, 2024
ec46e92
switch to constructor injection
maelanleborgne Sep 9, 2024
b26c12f
cleanup after review
maelanleborgne Oct 3, 2024
f97d4f5
Merge branch 'main' of github.com:Neirda24/GotenbergBundle into featu…
Neirda24 Oct 24, 2024
abd6e47
[UPDATE] Allow to set extra headers when using webhook
Neirda24 Oct 24, 2024
0c6cb61
[UPDATE] Auto docs
Neirda24 Oct 24, 2024
9fb37d7
[UPDATE] Remove custom id generator for the moment
Neirda24 Oct 31, 2024
ed70e51
[UPDATE] Remove strict types
Neirda24 Oct 31, 2024
f6509f6
[UPDATE] Docs
Neirda24 Oct 31, 2024
a40ec71
[UPDATE] Doc & doc generation
Neirda24 Nov 1, 2024
9faba1a
Merge branch 'main' of github.com:sensiolabs/GotenbergBundle into fea…
Neirda24 Nov 1, 2024
967bfad
[Fix] A few stuff
Neirda24 Nov 1, 2024
823faba
[UPDATE] A few stuff
Neirda24 Nov 1, 2024
83e1d26
[UPDATE] Add webhook methods
Neirda24 Nov 3, 2024
42a8544
[UPDATE] Exclude some methods to auto docs
Neirda24 Nov 3, 2024
a574f51
[UPDATE] Exclude some methods to auto docs
Neirda24 Nov 3, 2024
a9694cb
[UPDATE] Change equality check
Neirda24 Nov 3, 2024
8d39bd9
Update profiler icons + Fix webhook configuration + fix some tests
Neirda24 Nov 15, 2024
ebb4656
[Update] a few things
Neirda24 Nov 15, 2024
0f00fdf
fix typo
Neirda24 Nov 15, 2024
ee72e12
fix typo
Neirda24 Nov 15, 2024
eb474ad
Add documentation for webhook
Neirda24 Nov 16, 2024
44764dd
Update docs for webhooks
Neirda24 Nov 16, 2024
f8a1de9
Update docs for webhooks
Neirda24 Nov 16, 2024
c461a88
Add tests on async trait
Neirda24 Nov 16, 2024
931943a
[FIX] CI
Neirda24 Nov 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
.php-cs-fixer.cache
.phpunit.result.cache
composer.lock
phpstan.neon
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ class YourController
1. [Configuration](./docs/configuration.md)
2. [Working with assets](./docs/assets.md)
3. [Builders API](./docs/builders_api.md)
4. [Async & Webhooks](./docs/webhook.md)

#### PDF

Expand Down
6 changes: 6 additions & 0 deletions config/builder_pdf.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
->args([
service('sensiolabs_gotenberg.client'),
service('sensiolabs_gotenberg.asset.base_dir_formatter'),
service('.sensiolabs_gotenberg.webhook_configuration_registry'),
service('request_stack'),
service('twig')->nullOnInvalid(),
])
Expand All @@ -33,6 +34,7 @@
->args([
service('sensiolabs_gotenberg.client'),
service('sensiolabs_gotenberg.asset.base_dir_formatter'),
service('.sensiolabs_gotenberg.webhook_configuration_registry'),
service('request_stack'),
service('twig')->nullOnInvalid(),
service('router')->nullOnInvalid(),
Expand All @@ -47,6 +49,7 @@
->args([
service('sensiolabs_gotenberg.client'),
service('sensiolabs_gotenberg.asset.base_dir_formatter'),
service('.sensiolabs_gotenberg.webhook_configuration_registry'),
service('request_stack'),
service('twig')->nullOnInvalid(),
])
Expand All @@ -59,6 +62,7 @@
->args([
service('sensiolabs_gotenberg.client'),
service('sensiolabs_gotenberg.asset.base_dir_formatter'),
service('.sensiolabs_gotenberg.webhook_configuration_registry'),
])
->call('setLogger', [service('logger')->nullOnInvalid()])
->tag('sensiolabs_gotenberg.pdf_builder')
Expand All @@ -69,6 +73,7 @@
->args([
service('sensiolabs_gotenberg.client'),
service('sensiolabs_gotenberg.asset.base_dir_formatter'),
service('.sensiolabs_gotenberg.webhook_configuration_registry'),
])
->call('setLogger', [service('logger')->nullOnInvalid()])
->tag('sensiolabs_gotenberg.pdf_builder')
Expand All @@ -79,6 +84,7 @@
->args([
service('sensiolabs_gotenberg.client'),
service('sensiolabs_gotenberg.asset.base_dir_formatter'),
service('.sensiolabs_gotenberg.webhook_configuration_registry'),
])
->call('setLogger', [service('logger')->nullOnInvalid()])
->tag('sensiolabs_gotenberg.pdf_builder')
Expand Down
3 changes: 3 additions & 0 deletions config/builder_screenshot.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
->args([
service('sensiolabs_gotenberg.client'),
service('sensiolabs_gotenberg.asset.base_dir_formatter'),
service('.sensiolabs_gotenberg.webhook_configuration_registry'),
service('request_stack'),
service('twig')->nullOnInvalid(),
])
Expand All @@ -30,6 +31,7 @@
->args([
service('sensiolabs_gotenberg.client'),
service('sensiolabs_gotenberg.asset.base_dir_formatter'),
service('.sensiolabs_gotenberg.webhook_configuration_registry'),
service('request_stack'),
service('twig')->nullOnInvalid(),
service('router')->nullOnInvalid(),
Expand All @@ -44,6 +46,7 @@
->args([
service('sensiolabs_gotenberg.client'),
service('sensiolabs_gotenberg.asset.base_dir_formatter'),
service('.sensiolabs_gotenberg.webhook_configuration_registry'),
service('request_stack'),
service('twig')->nullOnInvalid(),
])
Expand Down
10 changes: 10 additions & 0 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use Sensiolabs\GotenbergBundle\GotenbergScreenshot;
use Sensiolabs\GotenbergBundle\GotenbergScreenshotInterface;
use Sensiolabs\GotenbergBundle\Twig\GotenbergAssetExtension;
use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry;
use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistryInterface;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\Filesystem\Filesystem;
use function Symfony\Component\DependencyInjection\Loader\Configurator\abstract_arg;
Expand Down Expand Up @@ -68,4 +70,12 @@
$services->set('sensiolabs_gotenberg.http_kernel.stream_builder', ProcessBuilderOnControllerResponse::class)
->tag('kernel.event_listener', ['method' => 'streamBuilder', 'event' => 'kernel.view'])
;

$services->set('.sensiolabs_gotenberg.webhook_configuration_registry', WebhookConfigurationRegistry::class)
->args([
service('router'),
service('.sensiolabs_gotenberg.request_context')->nullOnInvalid(),
])
->alias(WebhookConfigurationRegistryInterface::class, '.sensiolabs_gotenberg.webhook_configuration_registry')
;
};
199 changes: 199 additions & 0 deletions docs/async/native.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
## Using the native feature

Gotenberg [allows](https://gotenberg.dev/docs/configuration#webhook) to defer the generation of your files through webhooks.
When it is done creating your file, it calls back whatever header you sent.

To use this feature you need two things :
- Send the appropriate headers
- use `->generateAsync()` method

### Through Bundle configuration

Using bundle configuration you can define :
- named configurations
- default named configuration
- per context (PDF+HTML, PDF+URL, SCREENSHOT+MARKDOWN)

```yaml
# config/packages/sensiolabs_gotenberg.yaml

sensiolabs_gotenberg:

webhook:

# Prototype
name:
name: ~
success:

# The URL to call.
url: ~

# Route configuration.
route: ~

# Examples:
# - 'https://webhook.site/#!/view/{some-token}'
# - [my_route, { param1: value1, param2: value2 }]

# HTTP method to use on that endpoint.
method: null # One of "POST"; "PUT"; "PATCH"
error:

# The URL to call.
url: ~

# Route configuration.
route: ~

# Examples:
# - 'https://webhook.site/#!/view/{some-token}'
# - [my_route, { param1: value1, param2: value2 }]

# HTTP method to use on that endpoint.
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:

# Prototype
name:
name: ~
value: ~
default_options:

# Webhook configuration name.
webhook: ~
```

Each named configuration requires at least a `success` URL which can be set either through a plain URL (`sensiolabs_gotenberg.webhook.{name}.success.url`) or by using a defined route in your application (`sensiolabs_gotenberg.webhook.{name}.success.route`).

Here are some examples :

```yaml
sensiolabs_gotenberg:
webhook:
default:
success:
url: 'https://webhook.site/#!/view/{some-uuid}'
```
or
```yaml
sensiolabs_gotenberg:
webhook:
default:
success:
route: ['my_route', {'param1': 'value1'}]
```

Once a named configuration has been set, you can set it as a global default for all your builders :

```yaml
sensiolabs_gotenberg:
default_options:
webhook: 'default'
```

or set it per builder :

```yaml
sensiolabs_gotenberg:
webhook:
default:
success:
url: 'https://webhook.site/#!/view/{some-uuid}'
pdf_html:
success:
url: 'https://webhook.site/#!/view/{some-other-uuid}'
default_options:
pdf:
html:
webhook:
config_name: 'pdf_html'
```

finally you can do it like so :

```yaml
sensiolabs_gotenberg:
default_options:
pdf:
html:
webhook:
success:
url: 'https://webhook.site/#!/view/{some-uuid}'
```

> [!WARNING]
> When using both `config_name` and a custom configuration on a builder,
> it will load the named configuration and merge it with the builder's configuration.
>
> See the following example :

```yaml
sensiolabs_gotenberg:
webhook:
default:
success:
url: 'https://webhook.site/#!/view/{some-success-uuid}'
error:
url: 'https://webhook.site/#!/view/{some-error-uuid}'
default_options:
pdf:
html:
webhook:
config_name: 'default'
success:
url: 'https://webhook.site/#!/view/{some-other-uuid}'
```

is equivalent to :

```yaml
sensiolabs_gotenberg:
default_options:
pdf:
html:
webhook:
success:
url: 'https://webhook.site/#!/view/{some-other-uuid}'
error:
url: 'https://webhook.site/#!/view/{some-error-uuid}'
```

### At runtime

You can define webhook configuration at runtime.

If you defined some named configuration like seen earlier, the simplest way is then to do the following:

```diff
$builder = $this->gotenberg->pdf()->html()
+ ->webhookConfiguration('default')
->header('header.html.twig')
->content('html.html.twig', ['name' => 'Plop'])
->fileName('html.pdf')
;
```

Or you can also define manually using :

```diff
$builder = $this->gotenberg->pdf()->html()
+ ->webhookUrl($this->router->generate('my_route'))
->header('header.html.twig')
->content('html.html.twig', ['name' => 'Plop'])
->fileName('html.pdf')
;
```

> [!WARNING]
> If combining both `->webhookConfiguration()` & `->webhookUrl()`, the order is important :
>
> If calling `->webhookConfiguration()` first then `->webhookUrl()` will override only the "success" part.
>
> If calling `->webhookUrl()` first then `->webhookConfiguration()` totally overrides previously set values.


> [!NOTE]
> If only success URL is set, error URL will fallback to the success one.
16 changes: 9 additions & 7 deletions docs/builders_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

## Pdf

* [HtmlPdfBuilder](./pdf/builders_api/HtmlPdfBuilder.md)
* [UrlPdfBuilder](./pdf/builders_api/UrlPdfBuilder.md)
* [MarkdownPdfBuilder](./pdf/builders_api/MarkdownPdfBuilder.md)
* [LibreOfficePdfBuilder](./pdf/builders_api/LibreOfficePdfBuilder.md)
* [HtmlPdfBuilder](./Pdf/builders_api/HtmlPdfBuilder.md)
* [UrlPdfBuilder](./Pdf/builders_api/UrlPdfBuilder.md)
* [MarkdownPdfBuilder](./Pdf/builders_api/MarkdownPdfBuilder.md)
* [LibreOfficePdfBuilder](./Pdf/builders_api/LibreOfficePdfBuilder.md)
* [MergePdfBuilder](./Pdf/builders_api/MergePdfBuilder.md)
* [ConvertPdfBuilder](./Pdf/builders_api/ConvertPdfBuilder.md)

## Screenshot

* [HtmlScreenshotBuilder](./screenshot/builders_api/HtmlScreenshotBuilder.md)
* [UrlScreenshotBuilder](./screenshot/builders_api/UrlScreenshotBuilder.md)
* [MarkdownScreenshotBuilder](./screenshot/builders_api/MarkdownScreenshotBuilder.md)
* [HtmlScreenshotBuilder](./Screenshot/builders_api/HtmlScreenshotBuilder.md)
* [UrlScreenshotBuilder](./Screenshot/builders_api/UrlScreenshotBuilder.md)
* [MarkdownScreenshotBuilder](./Screenshot/builders_api/MarkdownScreenshotBuilder.md)

Loading