200が返るから、気づけなかった|孤立したAVIFが古い画像を返し続けていた話

変換後のファイルだけが残り古い画像が返され続ける構造を示した図 Web Development
この記事は約6分で読めます。

自分の作っているプラグインで、画像が古いまま返る不具合を見つけました。
原因は単純で、修正も1行でした。
ただ、見つかるまでの筋道と、なぜ気づきにくいのかのほうが書く価値があると思ったので、そちらを中心に残します。

症状

メディアライブラリで画像を完全に削除し、同じ名前で別の画像をアップロードする。
すると、古いほうの画像が返り続けます。
ブラウザキャッシュを消しても直りません。
そして、404 になりません。 200 で、古い画像が正常に返ります。

切り分け

まず、返っているものを測る

画面で確認しても分かりません。配送経路に何段も挟まっているので。
実際に返っているものを見ます。

PNG を要求して、AVIF が返っています。

そのバイト数を、ファイルと突き合わせる

一致しました。 そして、fig-a-1024x536.png は一覧に存在しません。

寸法で、別画像だと確定する

サイズ違いのファイル名には寸法が入るので、縦横比で世代を見分けられます。

18:12 のサイズ違いは、すべて .avif だけが残っていました。
PNG は消えている。AVIF は消えていない。

原因

.htaccess に書いていた、振り替えのルールです。

3行目が、変換後のファイルの存在しか見ていません。
元のリソースがまだあるかどうかは、条件に入っていませんでした。

添付ファイルのメタ情報に載っているものだけが削除され、変換後のファイルが残る構造を示した図

なぜ孤立するのか

WordPress の削除処理が消すのは、添付ファイルのメタ情報に載っているものだけです。
元のファイルと、sizes に登録されたサイズ違い。それ以外は知りません。
変換後のファイルは、後から別の工程で作られたものです。
メタ情報に載っていないので、削除の対象になりません。

手元の1枚で数えたら、24個のファイルができていました。 そのうち半分が変換後のものです。

修正

振り替えの条件に元ファイルの存在確認を足す前後の違いを示した図

条件を1つ足しました。

元のリソースがあるときだけ、振り替える。
無ければ振り替えず、そのまま 404 になります。
WebP 側にも同じ構造があったので、両方直しています。

削除時に、変換後も消す

ルールを直しただけでは、ファイルは残り続けます。
delete_attachment で、変換後のファイルも対象にしました。
元ファイルと、すべてのサイズ違いに対してです。
命名は拡張子の置換ではなく、後ろに付ける形です。

既存の孤立ファイル

すでに残っているものは、修正では消えません。探して消す必要があります。

いきなり削除する処理にはしていません。 件数を出して、確認してから消す形にしました。

気づきにくい理由

ここが、いちばん書きたかったところです。

1. 404 にならない

ファイルが無ければ 404 になる、という前提で調べます。
200 で返ってくると、配送の問題だと思いません。

2. 保存期間が長い

365日です。
原因ではありませんが、症状を長引かせます。
サーバー側を直しても、手元に残っていれば古いまま見えます。
「キャッシュを消しても直らない」と「キャッシュのせいで直ったように見えない」が混ざる。
切り分けが、そこで難しくなります。

3. キャッシュで説明がついてしまう

この症状は、2022年から報告されています。
調べていて、「ブラウザキャッシュだと思います」と回答されて解決済みとして閉じられているものを見かけました。
質問者はリロードもログインし直しも試していました。
それらしい説明が先にあると、そこで止まります。

同じ形の見落とし

PDF のサムネイルが真っ白になる件と、同じ構造でした。

どちらも「確認していない」ことによります。
そして、どちらも普段は問題になりません。
Ghostscript が新しければ白紙にならない。元のファイルが消えなければ孤立しない。
普段は成立する前提を、条件に書いていなかった。 それだけです。

他でも起こりうる構造です

この振り替えの書き方は、変換系のプラグインで広く使われています。
手元で確認した範囲では、複数の実装が同じ条件の書き方をしていました。
ただ、同じ手順で再現を取ったわけではないので、そこは断定しません。
これは欠陥というより、欠落だと思っています。
元ファイルが消えている状況を想定していなかった、というだけです。

学んだこと

存在確認は、片側だけでは足りない

「代わりのものがあるか」だけを見ると、こうなります。
置き換えるなら、置き換えられる側がまだ有効かどうかも見る。

管理外のファイルは、自分で面倒を見る

WordPress のメタ情報に載せずにファイルを作ると、ライフサイクルから外れます。
作った側が、削除まで責任を持つ。
フックを1つ足すだけの話でした。

200 は、正しさの証明ではない

これがいちばんこたえた部分です。
応答コードは、何かが返ったことしか示しません。
それが正しいものかどうかは、別の話でした。

確認した環境

この件は、修正版で解消しています。

症状と直し方だけ知りたい方向けの記事は、別に書きました。

Web Development
この記事を書いた人
rapls

WordPress のプラグインを作っているフリーランスエンジニア、Rapls です。Web 開発は6年以上。WordPress.org でプラグインを6本公開・保守しながら、日本語ロケールの翻訳エディター(PTE)も務めています。このブログには、現場で実際にハマって、調べて、直した話を書いています。

raplsをフォローする
raplsをフォローする

コメント

タイトルとURLをコピーしました