使用NodeJS清除AMP缓存

由于清除AMP缓存很繁琐,所以我做了个备忘录。
虽然有其他语言(PHP、Python),但没有NodeJS,所以我进行了实现。

以下是一个选项:

公式:https://developers.google.com/amp/cache/update-cache
引用1:https://beiznotes.org/amp-update-cache/
引用2:https://www.monotalk.xyz/blog/amp-%E7%9A%84%E6%9B%B4%E6%96%B0%E7%BC%93%E5%AD%98%E8%AF%B7%E6%B1%82%E4%BD%BF%E7%94%A8-apikeypub-%E5%8F%91%E9%80%81/

(Note: The URLs in the answer have been modified slightly for better readability in Chinese.)

需要创建私钥和公钥。

# 公開鍵、秘密鍵を作成
$ openssl genrsa 2048 > private-key.pem
$ openssl rsa -in private-key.pem -pubout > public-key.pem

将公钥(public-key.pem)重命名为https://{域名}/.well-known/amphtml/apikey.pub并存储,如果.well-known/amphtml文件夹不存在则创建。

apikey.pub需要以text/plain格式返回响应。
对于NginX而言,在/etc/nginx/mime.types中添加pub文件扩展名的默认Content-Type。

types {

     ...中略

     # 追加
     text/plain                                       pub; 
}

使用curl命令来验证是否返回text/plain格式的结果。

$ curl -I https://example.com/.well-known/amphtml/apikey.pub

假设将私钥文件放在/var/www/amp-keys/private-key.pem目录下,
假定域名为example.com(可根据需要更改)。

const axios = require('axios')
const fs = require('fs')
const crypto = require('crypto')
const program = require('commander')


// 環境変数
const DOMAIN = 'example.com'
// 秘密鍵のパス
const privateKeyPath = '/var/www/amp-keys/private-key.pem'

// AMPホスティングCDNのドメインを取得
async function getUpdateCacheApiDomainSuffix() {
  const data = await axios.get('https://cdn.ampproject.org/caches.json').then(res => res.data)
  const updateCacheApiDomainSuffixes = []
  for (let cache of data.caches) {
    updateCacheApiDomainSuffixes.push(cache.updateCacheApiDomainSuffix)
  }
  return updateCacheApiDomainSuffixes
}

// AMPUrlフォーマット:https://developers.google.com/amp/cache/overview#amp-cache-url-format
function AMPUrlFormat(url) {
  return url.replace('-', '--').replace('.', '-')
}

async function main() {

  program
   .version('1.0.0')
   .option('-p, --ampPath <ampPath>', 'ampPath')
   .parse(process.argv)

  const ampPath = program.ampPath
  if (!ampPath) {
    console.log('-p /amp/page')
    return
  }

  const updateCacheApiDomainSuffixes = await getUpdateCacheApiDomainSuffix()
  const ts = Math.floor(new Date().getTime() / 1000) // Unix秒(リクエスト時の60秒内に収めないといけない)

  const privateKey = fs.readFileSync(privateKeyPath)

  for (let updateCacheApiDomainSuffix of updateCacheApiDomainSuffixes) {
    const AMP_BASE_URL = `https://${AMPUrlFormat(DOMAIN)}.${updateCacheApiDomainSuffix}`
    const SIGNATURE_URL = `/update-cache/c/s/${DOMAIN}${ampPath}?amp_action=flush&amp_ts=`

    // AMP CacheのURLのドメイン部を除去した文字列をダイジェスト値として、電子署名を生成
    const url = SIGNATURE_URL + ts
    const sign = crypto.createSign('RSA-SHA256')
    sign.update(url)
    // 生成した電子署名をbase64エンコードし、`amp_url_signature` として使う。
    const signature = sign.sign(privateKey, 'base64')

    // update-cache の要求URLを生成し、リクエスト送付
    const ampUrl = AMP_BASE_URL + url + '&amp_url_signature=' + signature
    console.log(ampUrl)
    const result = await axios.get(ampUrl).then(res => res.data).catch(res => res.data)
    // 成功するとOK、指定のCDNにない場合は404エラーになる
    console.log(result)
  }

}
main()

执行时,使用-p选项指定AMP页面的路径,如下所示。

$ node amp-invalidate.js -p /amp/page

实际上,更常见的做法是通过使用sitemap.xml等来批量处理。

广告
将在 10 秒后关闭
bannerAds