Cloudflare Snippets (alpha) を使う

:::note info
2023年9月22日時点の情報です。
alpha のため、諸々の変更の可能性はあります。
:::

# Cloudflare Snippets
[Cloudflare Snippetsで最もプログラム可能なSupercloudを実現](https://blog.cloudflare.com/ja-jp/snippets-announcement-ja-jp/)

- JavaScript（モダン）、VCL（レガシー）、Apache .htaccessファイル（レガシー）など、様々な言語で書かれたコードのインポートをサポート
- Workers なしで、軽量な Workers 処理を柔軟に書ける
- すべてのプランレベルで追加料金なしで利用できる

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Cloudflare Snippets の発表！トラフィック操作に関して、出来合いの Rule 群に当てはまらない要件の場合、Snippets を書くことで追加費用なくカスタマイズ可能に。Snippets は、JavaScript / VCL / Apache .htaccess に対応予定。来年クローズドベータ開始予定。すごすぎる<a href="https://t.co/hH4EHyN5SX">https://t.co/hH4EHyN5SX</a></p>&mdash; kyhayama (@kyhayama) <a href="https://twitter.com/kyhayama/status/1593262850826735622?ref_src=twsrc%5Etfw">November 17, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

- [Cloudflare Snippetsはアルファ版で提供を開始](https://blog.cloudflare.com/ja-jp/cloudflare-snippets-alpha-ja-jp/)

アルファプログラムに参加したい方は、以下の waitlist にご参加ください。

https://www.cloudflare.com/en-gb/lp/cloudflare-snippets/

# 動作

[Cloudflare Snippets (alpha) · Cloudflare Rules docs](https://developers.cloudflare.com/rules/snippets/)

- Snippet Rule に対して Snippet を紐付ける
- 複数ルールマッチすれば、同じリクエストに対して Snippet が複数回、順次実行される
- 最大実行時間は5msで最大メモリは2MB、パッケージの合計サイズは32KB
- Origin Rules > Cache Rules > Configuration Rules > Single Redirects > Bulk Redirects > Snippets の順で実行
    - [Phases list · Cloudflare Ruleset Engine docs](https://developers.cloudflare.com/ruleset-engine/reference/phases-list/#phases-list)

# Snippet 作成
以下の手順で作成できます。

- [Create a snippet in the dashboard · Cloudflare Rules docs](https://developers.cloudflare.com/rules/snippets/create-dashboard/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/5ffa4120-206c-2cf1-4e1e-6cfc2065bae2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/6017058d-8355-8f9b-ceca-68b4df9dc81e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/0c9205e4-ec67-807d-2641-71730cc7fcda.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/c16e13b2-0331-3cba-2d7a-7c2b98f4878b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/1b961b33-1a28-8ba4-e23d-087d929693e1.png)

# デフォルト Snippet サンプル

まさに Workers の手前で動く Workers という形ですが、
Snippet Rule によって複数フィールドを使ったマッチ実行条件を設定できたりと、ルール群ならではの面もあります。

(Workers は カスタムドメインやルートトリガー等のホスト名条件で起動してしまう）

```javascript:sample_snippet.js
// Enter Snippet code bellow

export default {
    async fetch(request) {
        const response = await fetch(request);

        // Clone the response so that it's no longer immutable
        const newResponse = new Response(response.body, response);

        // Add a custom header with a value
        newResponse.headers.append(
            "x-snippets-hello",
            "Hello from Cloudflare Snippets"
        );

        // Delete headers
        newResponse.headers.delete("x-header-to-delete");
        newResponse.headers.delete("x-header2-to-delete");

        // Adjust the value for an existing header
        newResponse.headers.set("x-header-to-change", "NewValue");
        return new Response('Welcome to Cloudflare Snippets!');
    },
};
```

# 動作確認
デフォルトのサンプルコードだと、最後の行だけが実質有効なので、以下の結果となります。

```shell:
% curl -s https://snippet.example.com/     
Welcome to Cloudflare Snippets!
```

# Google Cloud Storage のプライベートオブジェクトにアクセス
以下の記事を参考にして、認証ヘッダをつける処理が Snippet で動くかを確認します。

- [Cloudflare Workers から HMAC 認証を使って Google Cloud Storage を fetch してキャッシュする - Qiita](https://qiita.com/khayama/items/04157a221d602d037114)
- [AWS Signature V4 を TypeScript でスクラッチ実装してみた](https://zenn.dev/mryhryki/articles/2022-08-15-aws-signature-v4#step1%3A-%E6%AD%A3%E8%A6%8F%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90)
- [Google Cloud Storage origin (private) | Fastly Developer Hub](https://developer.fastly.com/solutions/examples/google-cloud-storage-origin-private/)

環境変数が使えないため、以下のパラメータを直打ちします。

- バケット名 `YOUR_GCS_BUCKET_NAME`
- リージョン `asia-northeast1` 
    - [Bucket locations](https://cloud.google.com/storage/docs/locations#available-locations) によって変えてください。
- accessKeyId `YOUR_GCS_ACCESS_KEY_ID`
- secretAccessKey `YOUR_GCS_SECRET_ACCESS_KEY`

今後は [Cloudflare Secrets Store](https://blog.cloudflare.com/ja-jp/secrets-store-ja-jp/) にパラメータを保管して Snippet から利用できることが期待されます。

また、外部ライブラリの `import` が使えないため、ネイティブで書ける範囲で処理を行う必要があります。

https://gist.github.com/kyouheicf/46e46ac1de2a2ccf61c0e329de22c0c5

上記 Snippet を適用した上で、以下のようにアクセスできることが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/71ac8a6e-f123-b948-f021-f39d6d261450.png)

# まとめ
Workers のようで Workers でない Snippets でしたが、この程度の処理なら Snippets を使っていけそうです。

詳細なログの確認や [Secrets Store](https://blog.cloudflare.com/ja-jp/secrets-store-ja-jp/) との連携は今後に期待です。