New in Symfony 6.3: Webhook and RemoteEvent Components
Contributed by
Fabien Potencier
in #48542.
Webhooks are user-defined HTTP callbacks. They allow other services to alert
you about external events so you can respond to them. For example, consider the
packagist.org website that publishes information about PHP packages. Without
webhooks, that site would have to call GitHub, Gitlab, etc. repeatedly to see if
the code repositories of your packages changed.
Instead, packagist.org provides some webhooks that GitHub and others can call
to send your package details whenever you push new code. This way, the changes
are propagated almost immediately and none of these sites waste resources asking
other sites if things changed since last time.
Webhooks are so common and convenient that in Symfony 6.3 we’re introducing a
new Webhook component and a new RemoteEvent component. In Symfony, you
define a webhook as a parser + consumer. First, you create a parser able to handle
a certain type of webhook:
namespace AppWebhook;
use SymfonyComponentHttpFoundationChainRequestMatcher;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationRequestMatcherHostRequestMatcher;
use SymfonyComponentHttpFoundationRequestMatcherIsJsonRequestMatcher;
use SymfonyComponentHttpFoundationRequestMatcherMethodRequestMatcher;
use SymfonyComponentHttpFoundationRequestMatcherInterface;
use SymfonyComponentRemoteEventExceptionParseException;
use SymfonyComponentWebhookClientAbstractRequestParser;
use SymfonyComponentWebhookExceptionRejectWebhookException;
final class MailerWebhookParser extends AbstractRequestParser
{
protected function getRequestMatcher(): RequestMatcherInterface
{
// these define the conditions that the incoming webhook request
// must match in order to be handled by this parser
return new ChainRequestMatcher([
new HostRequestMatcher(‚github.com‘),
new IsJsonRequestMatcher(),
new MethodRequestMatcher(‚POST‘),
]);
}
protected function doParse(Request $request, string $secret): ?RemoteEvent
{
// in this method you check the request payload to see if it contains
// the needed information to process this webhook
$content = $request->toArray();
if (!isset($content[’signature‘][‚token‘])) {
throw new RejectWebhookException(406, ‚Payload is malformed.‘);
}
// you can either return `null` or a `RemoteEvent` object
return new RemoteEvent(‚mailer_callback.event‘, ‚event-id‘, $content);
}
}
Then, you create a consumer class able to process the remote event whose name
matches the one returned by the parser (in this example, the ‚mailer_callback.event‘ event):
use SymfonyComponentRemoteEventAttributeAsRemoteEventConsumer;
use SymfonyComponentRemoteEventRemoteEvent;
#[AsRemoteEventConsumer(name: ‚mailer_callback.event‘)]
class MailerCallbackEventConsumer
{
public function consume(RemoteEvent $event): void
{
// Process the event returned by our parser
}
}
This example showed just the most basic features of the new components, but there’s
much more. We’re still preparing the docs of these components, but meanwhile you
can watch for free the Fabien Keynote introducing Webhook and RemoteEvent
(in that link you will also find the slides).
Symfony Blog