nginxでbotに対してはキャッシュを見せたい

毎回、いまいちなクエリーでDBに問い合わせが発生するページがありまして、googleさんとかのBotでいっぱいいっぱいになることがあります。
かといって、古の遺産なのでいまさらリファクタリングツラい。工数かかる。

じゃあnginxでキャッシュすれば良くね？って思ったんだけど更新内容は**なるはや**で見せたいって要件もあってまたツラい。

- 人に対しては最新のページ
- Botさんに対しては数日前のキャッシュ

みたいなことができないかなー、と思ったので検証してみます。

## 検証環境

win10 Homeです。
Docker Toolbox入れます。
https://github.com/docker/toolbox/releases
一緒にdocker-composeも入れてます。
インストールして起動しました。

ひとまずデフォルトなnginxを動かします。

```yml:docker-compose.yml
version: '3'
services:
  nginx:
    image: nginx
    ports:
      - "8080:80"
    volumes:
      - ./content:/usr/share/nginx/html/content
      - ./conf.d:/etc/nginx/conf.d
      - ./cache:/usr/share/nginx/cache
```

```html:./content/index.html
<html>
  <body>
    Hello, 俺
  </body>
</html>
```

```config:./conf.d/default.conf
server {
    listen 80;
    server_name _;

    root  /usr/share/nginx/html;
    index index.html;

    access_log /var/log/nginx/access.log;
    error_log  /var/log/nginx/error.log;
}
```

```
$ docker pull nginx:latest
$ docker-compose up -d
$ docker-compose ps
     Name               Command          State          Ports
---------------------------------------------------------------------
dockers_nginx_1   nginx -g daemon off;   Up      0.0.0.0:8080->80/tcp
$ docker-machine ip
192.168.99.100
```

で、192.168.99.100を開くとdefaultのやつが表示される。

![192.168.99.100_8080_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308709/3ca5ef9d-c034-1140-7611-ed96b21e73bf.png)

ただ、192.168.99.100/content/ は403になって、なんか表示されなかったので、
コンテナ入ってindex.htmlを作り直してみた。ファイルのpermissionとかかな。

```
$ docker-compose.exe exec nginx bash  
```

そしたら表示された。なんか文字化けしてるけどここでは気にしない。

## キャッシュの設定

そんなわけでまずはキャッシュの設定。

```config:./conf.d/default.conf
proxy_cache_path /usr/share/nginx/cache keys_zone=zone1:1m levels=1:2;
server {
    listen 80;
    server_name _;

    root  /usr/share/nginx/html;
    index index.html;

    access_log /var/log/nginx/access.log;
    error_log  /var/log/nginx/error.log;

    location /content {
        proxy_cache zone1;
        proxy_cache_valid any 60m;
        proxy_pass http://localhost:81;
        break;
    }
}

server {
    listen 81;
    server_name _;

    root  /usr/share/nginx/html;
    index index.html;

    access_log /var/log/nginx/access81.log;
    error_log  /var/log/nginx/error81.log;
}
```

これを保存して、```docker-compose restart```を実行。
proxy_cacheはproxyで使うみたいなので別ポート立てつつ、同じコンテンツを見てます。
192.168.99.100/content/ を開くと、```./cache/``` にファイルができてる。

```bash
$ curl http://192.168.99.100:8080/content/                                                                                                 <html>
  <body>
    Hello,俺
  </body>
</html>

$ du -l ./cache
4       ./cache/0/81
4       ./cache/0
4       ./cache/e/7a
4       ./cache/e
8       ./cache
```

ここまでは普通

## Botと人で処理を分ける

これでどうだろうか。

```config:./conf.d/default.conf
proxy_cache_path /usr/share/nginx/cache keys_zone=zone1:1m levels=1:2;
server {
    listen 80;
    server_name _;

    root  /usr/share/nginx/html;
    index index.html;

    access_log /var/log/nginx/access.log;
    error_log  /var/log/nginx/error.log;

    set $nocache 1;
    if ( $http_user_agent ~* (bot|crawler) ) {
        set $nocache 0;
    }

    location /content {
        proxy_no_cache $nocache;
        proxy_cache_bypass $nocache;
        proxy_cache zone1;
        proxy_cache_valid any 60m;
        proxy_pass http://localhost:81;
        break;
    }
}

server {
    listen 81;
    server_name _;

    root  /usr/share/nginx/html;
    index index.html;

    access_log /var/log/nginx/access81.log;
    error_log  /var/log/nginx/error81.log;
}
```

htmlを更新しておきます。

```bash
$ sed -i 's/Hello/Bye/' content/index.html
$ cat content/index.html
<html>
  <body>
    Bye, 俺
  </body>
</html>
```

そしてDocker-compose restartして再確認

```
$ curl http://192.168.99.100:8080/content/
<html>
  <body>
    Bye,俺
  </body>
</html>
```

キャッシュじゃないのが返ってきた。
でもって、botの場合は・・

```
$ curl http://192.168.99.100:8080/content/ -H "User-Agent: hogehoge-bo
t (http://hogehoge)"
<html>
  <body>
    Hello,俺
  </body>
</html>
```

キャッシュが返ってきた！
いけました。
試しにキャッシュ消してみよう。

```
$ rm -rf ./cache/*
$ curl http://192.168.99.100:8080/content/ -H "User-Agent: hogehoge-bot (http://hogehoge)"
<html>
  <body>
    Bye,俺
  </body>
</html>
```

当然だけど最新のデータが返ってくる。
いけました！

これ(proxy_no_cache)使えばいけちゃうんですね。
http://www2.matsue-ct.ac.jp/home/kanayama/text/nginx/node65.html