Nginxで行うキャッシュ生成をmapディレクティブを使い再考する

4 min read

こんにちは、無能です。
頻繁にブログ記事を更新してると記事更新に合わせて過去のキャッシュを読み込んでほしくない。
ただし、出来る限りはキャッシュから配信したいので考えてみる。

ifでのキャッシュ判定をやめる

このような記事で紹介されている$do_not_cacheだとかでフラグ立ててその後にif文でキャッシュするコンテンツを変更しようという対応は現在は非推奨化されているようだ。
WordPressを爆速にするnginxのproxyキャッシュを冗長化しても共通で利用できるようにするアーキテクチャ(OpenResty+Redis)のご紹介

とは言うもののじゃあどこでキャッシュ判定をするか?

mapディレクティブではNginxの変数の内容を判定し、別の変数にその結果を値として代入します。

2022-03-01 Nginxのログをフィルタリングしてみる

そうして調べているととてもシンプルな構文が投稿されていた。
Adding location-block to cache files makes those files return 404

map $uri $expire {
    ~\.(?:j|cs)s$                      180d;
    ~\.(?:jpe?g|png|webp|woff2?|ttf)$  365d;
    default                            off;
}
map $uri $cache_control {
    ~\.(?:js|css|jpe?g|png|webp|woff2?|ttf)$  public;
}
server {
    ...
    expires $expire;
    add_header Pragma $cache_control;
    add_header Cache-Control $cache_control;
    ...
}

なるほど、わかりやすい。

目的のキャッシュ

基本的にhtmlファイル以外は長いキャッシュを保持させてhtmlファイルだけはちょっとキャッシュ出来るくらいでいい。
なぜかというとDOS、フラッド攻撃とかが来た場合に出来る限りNginxサーバ側に応答してほしいからで・・・。
一旦以下のように設定してみる。

map $uri $expire {
    ~\.(jpg|jpeg|png|webp|gif|mp4|css|js|ico|woff2)(\?.*)?$ 365d;
    ~\.html$ 5m;
}

map $uri $cache_control {
    ~\.(jpg|jpeg|png|webp|gif|mp4|css|js|ico|woff2)(\?.*)?$ public;
    ~\.html$ public;
}

これでnginx -tservice nginx restartをしてcurlでテストしてみる。

リクエストURIにhtmlが存在しなければキャッシュしてくれない・・・。

どうやら、htmlファイルをキーとしてキャッシュするようにしているのでドメイン単位でキャッシュしようとはしてくれない。

alleycat:[haturatu]:~/git$ curl -I https://soulminingrig.com
HTTP/2 200 
server: nginx/1.27.0
date: Sat, 23 Nov 2024 12:20:55 GMT
content-type: text/html
content-length: 15699
vary: Accept-Encoding
last-modified: Sat, 23 Nov 2024 12:08:31 GMT
etag: "3d53-627935ba8f789"
accept-ranges: bytes
vary: Accept-Encoding
content-security-policy: upgrade-insecure-requests
alt-svc: h3=":443"; ma=86400
x-content-type-options: nosniff

alleycat:[haturatu]:~/git$ curl -I https://soulminingrig.com/index.html
HTTP/2 200 
server: nginx/1.27.0
date: Sat, 23 Nov 2024 12:21:00 GMT
content-type: text/html
content-length: 15699
vary: Accept-Encoding
last-modified: Sat, 23 Nov 2024 12:08:31 GMT
etag: "3d53-627935ba8f789"
accept-ranges: bytes
vary: Accept-Encoding
expires: Sat, 23 Nov 2024 12:26:00 GMT
cache-control: max-age=300
content-security-policy: upgrade-insecure-requests
alt-svc: h3=":443"; ma=86400
x-content-type-options: nosniff
pragma: public
cache-control: public

curl -I https://soulminingrig.comをしたときにcache-controlの情報が欠落しているということはこのキャッシュ判定にいれられていない。
実際にはindex.htmlを表示しているのだが判定としてNginx側は理解してくれてはいないので、今度はこうしてみる。

map $uri $expire {
    ~\.(jpg|jpeg|png|webp|gif|mp4|css|js|ico|woff2)(\?.*)?$ 365d;
    ~\.html$ 5m;
    ~\.*$ 5m;
}

map $uri $cache_control {
    ~\.(jpg|jpeg|png|webp|gif|mp4|css|js|ico|woff2)(\?.*)?$ public;
    ~\.html$ public;
    ~\.*$ public;
}

こうすれば問答無用で正規表現でなんでも5分はキャッシュを保持してくれるようになる。
再度curl -Iをしてみよう。

alleycat:[haturatu]:~/git$ curl -I https://soulminingrig.com
HTTP/2 200 
server: nginx/1.27.0
date: Sat, 23 Nov 2024 12:44:43 GMT
content-type: text/html
content-length: 15699
vary: Accept-Encoding
last-modified: Sat, 23 Nov 2024 12:08:31 GMT
etag: "3d53-627935ba8f789"
accept-ranges: bytes
vary: Accept-Encoding
expires: Sat, 23 Nov 2024 12:49:43 GMT
cache-control: max-age=300
content-security-policy: upgrade-insecure-requests
alt-svc: h3=":443"; ma=86400
x-content-type-options: nosniff
pragma: public
cache-control: public

alleycat:[haturatu]:~/git$ curl -I https://soulminingrig.com/top.png
HTTP/2 200 
server: nginx/1.27.0
date: Sat, 23 Nov 2024 12:44:47 GMT
content-type: image/png
content-length: 46584
vary: Accept-Encoding
last-modified: Sat, 23 Nov 2024 12:08:31 GMT
etag: "b5f8-627935ba12787"
accept-ranges: bytes
expires: Sun, 23 Nov 2025 12:44:47 GMT
cache-control: max-age=31536000
content-security-policy: upgrade-insecure-requests
alt-svc: h3=":443"; ma=86400
x-content-type-options: nosniff
pragma: public
cache-control: public

alleycat:[haturatu]:~/git$ curl -I https://soulminingrig.com/index.html
HTTP/2 200 
server: nginx/1.27.0
date: Sat, 23 Nov 2024 12:44:51 GMT
content-type: text/html
content-length: 15699
vary: Accept-Encoding
last-modified: Sat, 23 Nov 2024 12:08:31 GMT
etag: "3d53-627935ba8f789"
accept-ranges: bytes
vary: Accept-Encoding
expires: Sat, 23 Nov 2024 12:49:51 GMT
cache-control: max-age=300
content-security-policy: upgrade-insecure-requests
alt-svc: h3=":443"; ma=86400
x-content-type-options: nosniff
pragma: public
cache-control: public

無事に全てキャッシュしてくれるようになった。

これでキャッシュすることによってかなり設定ファイルの構文が短くなったしキャッシュ設定を変更したいときにはmapディレクティブの変更をすればよいだけになったので快適になりました。
それでは。またよろしくおねがいします。