使用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&_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 + '&_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等来批量处理。