API Gateway+LambdaでmicroCMSとS3をsyncする


やりたいこと

当ブログ ( https://tech.ysk1o.com ) では、記事の管理にmicroCMSを使用しています。
画像は microcms にホストしていますが、これを自分の環境でホストしたくなりました。

画像はS3にアップロードし、 Route53 + CloudFront + S3 という形でホストしています。
CloudFrontからのみS3にアクセスさせる方法は以下です。

参考: CloudFrontからのみS3バケットへのアクセスを許可する(作成中)

手順

Lambdaを作成する

microCMSからのパラメータに記載されているURLから画像を取得して
S3に 追加 / 編集 / 削除 する関数を作成します。

IAM

S3へのアクセスは以下のようなポリシーをあててます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:DeleteObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3::: < S3 URL > /*"
        }
    ]
}

Sampleコード

以下に、追加する部分だけ簡単にサンプルのコードを載せてみました。

// microCMSから渡ってくるパラメータのサンプル
const event = {
   service: '< microCMS service name >',
   type: '{new,update,delete}',
  old: {
     url: '< Image URL >',
     width: 200,
    height: 199
  },
  new: {
    url: '< Image URL >',
    width: 200,
    height: 199
  },
};

// node-fetchはLambdaではデフォルトで使えないので注意
const fetch = require('node-fetch');
const cmsImageData = await fetch(event.new.url, {
  headers: { 'Content-Type': contentType },
});
const bufferData = await response.buffer();

const params = {
  Body: bufferData,
  Bucket: bucketName,    // バケット名を指定
  Key: '< s3 path >',    // 画像URLからs3のpathを作成
  ContentType: 'image/{jpeg,png}',    // 画像から拡張子を特定して指定
};

// S3にアップロードする
const AWS = require('aws-sdk');
const s3 = new AWS.S3({ apiVersion: '2006-03-01' });
await s3.putObject(params).promise();

API Gatewayを作成する

Create MethodボタンからPOSTを選択して、接続先に上記で作成したLambdaを指定すればOK。
その後、デプロイするとURLが発行されるので、控えておきます。

microCMSのWebhookの設定をする

上記で、API Gateway + Lambda でS3と画像をsyncする関数とエンドポイントができました。
このエンドポイントをmicroCMSのWebhookに設定していきます。

microCMSのドキュメント がわかりやすいので実際の設定は省略しますが
URLを記載するところに、先ほど控えたAPI GatewayのエンドポイントURLを設定します。

さいごに

今回やりたかったことは上記で満たすことはできました。
ただ正直、このやり方で正しかったのかと言われると、、

それはmicroCMSにも同じものがホストされてるからです。

S3にアップロードしたらmicroCMSから消す、みたいなこともやろうと思えばできると思いますが
記事に貼ってあるリンクとの整合性を保ちづらくなるしアセット自体の管理もままなりません
そこまでするなら他のサービスを検討するか、公式の対応を待つのがいいかなと思います。

microCMSはimgixの画像編集APIを裏側で使用しており、先日パートナー契約を締結したそうです。
そして、 imgix はカスタムドメインでのホスティングに対応しているので
microCMSを通じてこの機能を使用できたらなあ、と妄想しています。

『microCMS』、imgixと国内初となるパートナー契約を締結

https://prtimes.jp/main/html/rd/p/000000005.000062982.html

If you want to use a custom domain as the base URL for your Source, you can add one. Both the standard subdomain and the custom will resolve to the same Origin Image. You can add up to 100 imgix subdomains and custom domains.

https://docs.imgix.com/setup/creating-sources/advanced-settings#custom-domains