Cloudinaryで一度fetchしたオリジン画像を更新する
Cloudinaryではリモートサーバーにある画像をオンデマンドで取得する機能が2種類存在します
- Fetch : リモートのリソースをマスターとして活用。Cloudinaryで一度キャッシュされると、定期的(デフォルトでは7日)に再取得
- Auto-Upload : Cloudinaryに一度取り込まれると、以降はCloudinaryのリソースをマスターとして利用。
前者の Fetch 機能を利用すると、リモートサーバーのリソースが更新されても、Cloudinaryが定期的にプルするまで更新リソースが配信されません。
今回は Upload API の destory メソッドを呼び出し、即座に新しいリソースを配信する方法を紹介します。
やってみた
以下のシナリオで動作確認します。
- リモートのリソースを fetch → 新規にfetchされる
- リモートのリソースを更新
- fetch URL をもう一度リクエスト → fetch 済み & CDN キャッシュ済みリソースが返される
- Upload API の Destory メソッドを実行
- fetch URL をもう一度リクエスト → 再度 fetch し、更新したリソースが返される
1. リモートのリソースを fetch
Fetch 機能を利用し、リモートサーバーのリソース(https://example.com/dog.png)を fetch します。
$ curl -I https://res.cloudinary.com/demo/image/fetch/https://example.com/dog.png HTTP/2 200 access-control-allow-origin: *s cache-control: public, max-age=604800 content-type: image/png edge-cache-tag: 344131525993202736795913186797227682751,2ec1e12c84e9ec6781dfb3e75d59aba9 etag: "e1a0f56a8bd70af6335a0ba7eb24803e" last-modified: Thu, 12 Sep 2019 17:06:39 GMT server: cloudinary status: 200 OK timing-allow-origin: * x-request-id: 342bd4182ec8c368 accept-ranges: bytes date: Thu, 12 Sep 2019 17:06:38 GMT via: 1.1 varnish age: 0 x-served-by: cache-hhn4035-HHN x-cache: MISS x-cache-hits: 0 x-timer: S1568307998.203637,VS0,VE724 access-control-allow-headers: X-Requested-With,Range,User-Agent access-control-expose-headers: Content-Length content-length: 8311
初めてのリクエストのため、キャッシュミスしています(x-cache: MISS
)。
また、このリソースは
- etag: "e1a0f56a8bd70af6335a0ba7eb24803e"
- content-length: 8311
であることがわかります。
2. リモートのリソースを更新
リモートのリソースを更新し、リモートサーバーに直接 GET リクエストします。
$ curl -I https://example.com/dog.png HTTP/1.1 200 OK x-amz-id-2: MwDPqXCPzDQfqkp0mEaoCPSwAkdrtZ762IdHA2mqybY+Ub1ecMllDsyfP56pRFfQL3Q8IvJlTrQ= x-amz-request-id: FB4BF2113639BFA3 Date: Thu, 12 Sep 2019 17:10:09 GMT Last-Modified: Thu, 12 Sep 2019 17:09:24 GMT ETag: "44eb7c121b77323596bca1cea1add715" Accept-Ranges: bytes Content-Type: image/png Content-Length: 154414 Server: AmazonS3
更新後のリソースは
- etag: "44eb7c121b77323596bca1cea1add715"
- content-length: 154414
であることがわかります。
3. fetch URL をもう一度リクエスト
ステップ #1 の fetch URL をもう一度リクエストします。
$ curl -I https://res.cloudinary.com/demo/image/fetch/https://example.com/dog.png HTTP/2 200 access-control-allow-origin: * cache-control: public, max-age=604800 content-type: image/png edge-cache-tag: 344131525993202736795913186797227682751,2ec1e12c84e9ec6781dfb3e75d59aba9 etag: "e1a0f56a8bd70af6335a0ba7eb24803e" last-modified: Thu, 12 Sep 2019 17:06:39 GMT server: cloudinary timing-allow-origin: * accept-ranges: bytes date: Thu, 12 Sep 2019 17:07:20 GMT via: 1.1 varnish age: 3 x-served-by: cache-fra19174-FRA x-cache: HIT x-cache-hits: 1 x-timer: S1568308041.799637,VS0,VE0 access-control-allow-headers: X-Requested-With,Range,User-Agent access-control-expose-headers: Content-Length content-length: 8311
x-cache: HIT
からキャッシュヒットしていることがわかり、etag
とcontent-length
から fetch 済みリソースが返されていることがわかります。
4. Upload API の Destory メソッドを実行
Upload API の Destory メソッドを呼び、Cloudinary にキャッシュされた古いリソースを削除し、Cloudinary の CDN からパージします。
Python 版 Destroy プログラム
import cloudinary import cloudinary.uploader cloudinary.config( cloud_name = "XXX", api_key = "XXX", api_secret = "XXX" ) public_id = "https://example.com/dog.png" result = cloudinary.uploader.destroy( public_id, type="fetch", invalidate=True) print(result)
フェッチリソースの場合、 type="fetch"
を指定し、public_id
にはリモートリソースの URL を指定します。
Cloudinaryは画像・動画配信のワンストップソリューションで、CDN も内蔵しています。CDN キャッシュをパージするため、 invalidate=True
の引数も渡します。
Cloudinary の Python SDK の使い方は、次の過去記事を参照ください。
Destroy の実行
このプログラムを呼び出します。
$ python destroy.py {'result': 'ok'} $
5. Destroy 後に fetch URL をリクエスト
Cloudinary 内のリソースを削除し、CDN キャッシュをパージすると、レスポンスはどのように変わるでしょうか?
$ curl -I https://res.cloudinary.com/demo/image/fetch/https://example.com/dog.png HTTP/2 200 access-control-allow-origin: * cache-control: public, max-age=604800 content-type: image/png edge-cache-tag: 344131525993202736795913186797227682751,2ec1e12c84e9ec6781dfb3e75d59aba9 etag: "44eb7c121b77323596bca1cea1add715" last-modified: Thu, 12 Sep 2019 17:13:14 GMT server: cloudinary status: 200 OK timing-allow-origin: * x-request-id: 0eb56443c5f7dba1 accept-ranges: bytes date: Thu, 12 Sep 2019 17:13:13 GMT via: 1.1 varnish age: 0 x-served-by: cache-fra19176-FRA x-cache: MISS x-cache-hits: 0 x-timer: S1568308393.699648,VS0,VE1105 access-control-allow-headers: X-Requested-With,Range,User-Agent access-control-expose-headers: Content-Length content-length: 154414
x-cache: MISS
からキャッシュミスしていることがわかり、etag
とcontent-length
から更新後の新しいリソースが返されている、つまり、リモートサーバーに fetch したことがわかります。
コンソールからも新しいリソースであることを確認してください。
コンソールからの削除操作
コンソールの Media Library にはフェッチされたリソースも表示されます。
コンソールからこのリソースを削除すると、 Destroy メソッドを実行したのと同等の操作となります。
無効化時に利用できる URL 形式は複数
キャッシュを無効化する時に利用する URL 形式は複数種類あり、アカウントごとに切替可能です。
通常は URL 形式の違いを意識する必要はなく、デフォルトのままで問題ありませんが、オブジェクトのバージョンごとの配信(cache busting)を行っているような場合、配信方式にあった無効化処理が必要です。
詳細は次のドキュメントを参照ください。
What URL conventions are invalidated – Cloudinary Support
最後に
Cloudinary で一度 fetch した画像を更新する方法を紹介しました。
プロダクション運用では、オリジンサーバーの画像系リソースの更新イベントをトリガーに Cloudinary へ Upload::destory
メソッドを呼び出し、CloudinaryコンソールのリソースキャッシュとCDNキャッシュを削除すると、サービス全体でコンテンツ更新のタイムラグが発生しなくなるかと思います。
具体的な構成例は次の記事で紹介しています。
AWS Lambda PythonからCloudinaryを操作してみた | Developers.IO
VarnishCloudinary は素晴らしいですね!
それでは。