0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Symfony ComponentAdvent Calendar 2023

Day 16

外部サービスからのイベントを受け取るよ(後編)、"RemoteEvent"

Last updated at Posted at 2023-12-15

Symfony Component Advent Calendar 2023の16日目の記事です。

外部サービスからのイベントを受け取るよ、"RemoteEvent"

RemoteEventは、外部サービスからのイベントを『リモートからのイベント』とみなし、イベントを発火させるコンポーネントです。

インストール

composer require symfony/remote-event

使い方

Symfonyの偉い人は考えました。『Webhookって要はリモートからのイベントじゃん。』
webhookでSymfonyにアクセスされた時、それをRemoteEventに置き換えてイベント発火させ、処理を行います。処理の流れはこんな感じです。

  1. 外部サービスのwebhookを解析するRequestParserを作る
  2. 解析したリクエストをRemoteEventにする
  3. イベントを受け取って実行するConsumerを作る
  4. webhookとして設定する

このうち、3,4は前編のWebhookとして説明しましたが、再度記載します。

1. RequestParserを作る & 2. RemoteEventを作る

SampleWebhookParser.php

namespace App\Webhook;

use Symfony\Component\HttpFoundation\ChainRequestMatcher;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestMatcher\HostRequestMatcher;
use Symfony\Component\HttpFoundation\RequestMatcher\IsJsonRequestMatcher;
use Symfony\Component\HttpFoundation\RequestMatcher\MethodRequestMatcher;
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
use Symfony\Component\RemoteEvent\RemoteEvent;
use Symfony\Component\Webhook\Client\AbstractRequestParser;

class SampleWebhookParser extends AbstractRequestParser
{

    protected function getRequestMatcher(): RequestMatcherInterface
    {
        return new ChainRequestMatcher([
            new HostRequestMatcher('github.com'),
            new IsJsonRequestMatcher(),
            new MethodRequestMatcher('POST')
        ]);
    }

    protected function doParse(Request $request, #[\SensitiveParameter] string $secret): ?RemoteEvent
    {
        $content = $request->toArray();
        return new RemoteEvent('sample', 1, [
            'name' => $content['repository']['full_name'],
            'action' => $content['action'],
            'secret' => $secret,
        ]); // RemoteEvent('{イベント名}', '{イベントID}', {ペイロード})
    }
}

getRequestMatcher()でどのURLからアクセスされたものをRemoteEventにするか設定します。
上記の場合、

  • github.comからのアクセス
  • リクエストボディがJSON
  • メソッドがPOST

の場合に、このクラスのdoParse()が実行されます。
doParse()では、Requestオブジェクトを使って、リクエスト内容を取得し、その内容を使ってRemoteEventオブジェクトを作って返します。

3. Consumerを作る

SampleEventConsumer.php

namespace App\RemoteEvent;

use Symfony\Component\RemoteEvent\Attribute\AsRemoteEventConsumer;
use Symfony\Component\RemoteEvent\Consumer\ConsumerInterface;
use Symfony\Component\RemoteEvent\Event\Mailer\AbstractMailerEvent;
use Symfony\Component\RemoteEvent\Event\Mailer\MailerDeliveryEvent;
use Symfony\Component\RemoteEvent\RemoteEvent;
use Symfony\Contracts\EventDispatcher\Event;

#[AsRemoteEventConsumer(name: 'sample')]
class SampleEventConsumer implements ConsumerInterface
{
    public function __construct(private readonly LoggerInterface $logger)
    {
    }
    
    public function consume(RemoteEvent $event): void
    {
        $payload = $event->getPayload();
        $name = $payload['name'];
        $action = $payload['action'];
        $this->logger->info("{$name}: {$action}");
    }
}

#[AsRemoteEventConsumer]に2で作成したRemoteEventのイベント名を設定します。そうすることで、RemoteEventが発火した際にこのConsumerのconsume()が実行されます。
consume()内は、やりたいことを好きに書いてください。気をつけないといけないのはこのメソッドはvoidなので、何も返しません。

4. webhookの設定

config/packages/webhook.yaml
framework:
    webhook:
        routing:
            sample:
                service: 'App\Webhook\SampleWebhookParser'

webhookの設定を行います。この設定により、/webhook/sampleで、github.comからPOSTでJSONを送られてきた時用のwebhookが作成されます。

まとめ

今回はRemoteEventでした。Webhookで定義されていない外部サービスでも、このようにすればwebhookを作成することができます!

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?