arrow-righthamburgerlogo-marksocial-facebooksocial-githubsocial-twitter
2019.02.12

CloudflareのAPIをNode.js+GitLab CIから実行してキャッシュクリアしてみよう

のびすけ

Node.js Magazine
   このエントリーをはてなブックマークに追加  

こんにちは、n0bisukeです。

過去にも書いているように、dotstudioではCloudflareを使っています。

無料で使えて便利なのですが、キャッシュが強くて中々更新されないといった現象があります。

調べてみるとCloudflareのAPIでキャッシュクリアが出来るみたいだったのでNode.jsで叩きつつデプロイ時のCIタスクに乗せてみました。

今回の環境

参考までに今回の筆者の環境です。

Cloudflareでのキャッシュクリア方法

APIを使わない場合は、ページから直接削除できます。

Custom Purgeのボタンを押すと、モーダルウィンドウが出てくるのでキャッシュクリアしたいドメインやページを指定しましょう。

こんな感じの指定が出来ます。

記述したらPurgeボタンを押してキャッシュクリアです。

確認する際ですが、ブラウザ側のキャッシュが残ってしまってる可能性もあるので、ブラウザのシークレットモードなどでページを開いてあげると確実だと思います。

API経由でCloudflareのキャッシュをクリア

デプロイ時にキャッシュクリアをしたいので、API経由でキャッシュクリアをしてみましょう。

CloudflareのAPI キーの取得

まずはAPIキーを取得します。右上のユーザーアイコンからMy Profileを選択し、ページ下部のAPI Keysの箇所を確認します。

Global API KeyのViewボタンを押すとパスワード入力を求められるので、パスワードを入力するとAPIキーが表示されます。

APIキーを使ってcurlでキャッシュクリアをしてみる

参考記事を元に試してみます。最初からNode.jsでやりたい人はスキップでOKです。

参考: CloudFlare APIを使ってキャッシュを削除する

CloudflareのAPIの呼び出しはヘッダーにはX-Auth-EmailX-Auth-Keyの指定、Content-Type: application/jsonの指定をする必要があります。

手順としては大きく分けて2つSTEPです。

以下のコマンドをターミナルなどで実行してみましょう。

STEP1. ZONE IDと呼ばれるIDを取得

まずはZONE IDの取得です。以下のコマンドで取得できます。

curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=<MY DOMAIN>" -H "X-Auth-Email: <MY EMAIL>" -H "X-Auth-Key: <MY API KEY>" -H "Content-Type: application/json"

<MY DOMAIN><MY EMAIL><MY API KEY>の箇所を適宜変更して実行して下さい。

それぞれ、自分が管理しているドメイン、登録しているメールアドレス、先ほど取得したAPIキーです。

コマンドを実行してエラーがなければ、JSONがかえってきます。ここのidの値がZONE IDになります。

{"result":[{"id":"yyyyyyyyyyyyyyyyyyyy","name":"dotstud.io","status":"active","paused":false,"type":"full", (......以下省略)

STEP2. ZONE IDを使ってキャッシュクリア

次にZONE IDを使ってキャッシュクリアです。

curl -X DELETE "https://api.cloudflare.com/client/v4/zones/<ZONE ID>/purge_cache" -H "Content-Type:application/json" -H "X-Auth-Key: <MY EMAIL>" -H "X-Auth-Email: <MY API KEY>" --data '{"files":["<TARGET>"]}'

先ほどと同様に適宜変更します。

<ZONE ID><MY EMAIL><MY API KEY><TARGET>の箇所を適宜変更して実行して下さい。

<ZONE ID>はSTEP1で取得したZONE IDで、<TARGET>はキャッシュクリアさせたいドメインやファイル名の指定です。最初にAPI利用なしでCloudflareのサイト上でキャッシュクリアをした時に指定したときと同様の指定ができます。

成功すると以下のようなレスポンスがあり、キャッシュがクリアされます。

{"result":{"id":"yyyyyyyyyyyyyyyyyyyy"},"success":true,"errors":[],"messages":[]}%

Node.jsでAPIを叩いてみる

まずはフォルダやファイルの準備をしましょう。 mycfフォルダ内にpurge_cache.jsというファイルを作成します。

mkdir mycf
cd mycf
touch purge_cache.js

HTTPリクエストを利用する為にaxiosをインストールします。

npm init -y
npm i axios

purge_cache.jsに以下の内容をコピペして、YOUREMAILAPIKEYPURGE_TARGETSを適宜書き換えましょう。

'use strict';

const YOUREMAIL = `[email protected]`; //Cloudflareに登録してるメールアドレス
const APIKEY = `xxxxxxxxxxxxxxxxx`; //CloudflareのAPI KEY
const PURGE_TARGETS = [`https://hogehoge.dotstud.io`]; //消す対象ページ

const axiosBase = require('axios');
const axios = axiosBase.create({
    baseURL: `https://api.cloudflare.com/client/v4/zones`,
    headers: {
        'Content-Type': 'application/json',
        'X-Auth-Key': APIKEY,
        'X-Auth-Email': YOUREMAIL
    }
})

const main = async() => {
    try {
        //STEP1. ZoneIDの取得
        let res = await axios.get('/');
        const zoneid = res.data.result[0].id;

        //STEP2. キャッシュ削除
        res = await axios.delete(`/${zoneid}/purge_cache`,{
            data: {
                files: PURGE_TARGETS
            }
        });
        console.log(res.data);
    } catch (error) {
        console.log(error.response.data)
    }

}

main();

実行します。エラーが出なければこれでキャッシュクリアされます。

node purge_cache.js

これでNode.jsからCloudflareのキャッシュクリアをすることが出来ました。

GitLab CIのタスクで実行する

実際にデプロイした際にキャッシュクリアされるようにしたいのでGitLab CIのタスクに入れ込みました。

ソースコードの変更

先ほどソースコード上に書いていたYOUREMAILなどの値は環境変数から取得するようにpurge_cache.jsを変更しました。また、最後(STEP3)にDiscordにデプロイ成功を通知する処理も追加しています。

'use strict';

if(!process.env.YOUREMAIL || !process.env.APIKEY || !process.env.PURGE_TARGET){
    console.log('環境変数が足りません');
    return;
}

const YOUREMAIL = process.env.YOUREMAIL; //Cloudflareに登録してるメールアドレス
const APIKEY = process.env.APIKEY; //CloudflareのAPI KEY
const PURGE_TARGETS = [process.env.PURGE_TARGET]; //消す対象ページ

const axiosBase = require('axios');
const axios = axiosBase.create({
    baseURL: `https://api.cloudflare.com/client/v4/zones`,
    headers: {
        'Content-Type': 'application/json',
        'X-Auth-Key': APIKEY,
        'X-Auth-Email': YOUREMAIL
    }
})

const main = async() => {
    try {
        //STEP1. ZoneIDの取得
        let res = await axios.get('/');
        const zoneid = res.data.result[0].id;

        //STEP2. キャッシュ削除
        res = await axios.delete(`/${zoneid}/purge_cache`,{
            data: {
                files: PURGE_TARGETS
            }
        });
        console.log(res.data);

        //STEP3. Discordへ通知
        res = await axiosBase.post(process.env.DISCORD_WEBHOOK_URL,{
            content: 'デプロイ成功 & キャッシュクリア'
        });
        console.log(res.data);

    } catch (error) {
        console.log(error.response.data)
    }

}

main();

package.jsonの変更

また、先日書いた記事にもあるような、VuePressのデプロイフローに今回のタスクを乗せていきます。

package.jsonci:purge_cacheを追加してpurge_cache.jsを実行するスクリプトを追加します。

(省略)

"scripts": {
    "dev": "vuepress dev docs",
    "build": "vuepress build docs",
    "ci:purge_cache": "node purge_cache.js",
  },

(省略)

.gitlab-ci.ymlの変更

GitLab CIの挙動として.gitlab-ci.ymlの記述は以下のようにしています。

after_scriptの箇所でnpm run ci:purge_cacheをすることで、デプロイが終わった後にpurge_cache.jsが実行されてキャッシュクリアがされます。

image: node:current-alpine

pages:
  cache:
    paths:
    - node_modules/
  before_script:
    - node -v
    - npm i
  script:
    - npm run build
    - cp docs/robots.txt docs/.vuepress/dist #限定公開の場合
    - cp -pr docs/.vuepress/dist public
  after_script:
    - npm run ci:purge_cache #Cloudflareのキャッシュクリア & Discordへ通知
  artifacts:
    paths:
      - public
  only:
    - master

環境変数の登録

GitLabのリポジトリから環境変数を追加することができます。

リポジトリのSettings>CI/CDからEnvironment variablesの箇所を開きます。

各値を名前をソースコードに記述した変数名と一致させつつ設定しましょう。

まとめ

ここまでの手順が出来るとデプロイするたびに、Cloudflareのキャッシュがクリアされて、なかなか更新されない問題が解消できると思います。

これでもページが更新されない場合はブラウザ側でキャッシュされている可能性が高いのでシークレットモードなどで確認したり、ブラウザを変えてみるのがベターだと思います。

キャッシュコントロールをしてCloudflareをもっと便利に使っていきましょう。

それでは!

   このエントリーをはてなブックマークに追加