意味のないリクエストパラメータを追加してキャッシュを回避してみよう

## はじめに

ブラウザ側にレスポンスデータのキャッシュがあると、サーバ側の修正がブラウザ側に反映されないことがあります。

キャッシュが効きすぎて、サーバ側の修正を確認することができないということになりかねません。

『独習JavaScript』第２版のP353にキャッシュを回避する例(意味のないリクエストパラメータを追加する例)が紹介されていましたので、それを試してみたいと思います。

この記事では、ブラウザ側でレスポンスデータをキャッシュすることを確認して、その後、意味のないリクエストパラメータを追加したときにキャッシュを回避することを確認します。

なお、PlayFrameworkのキャッシュを紹介する際には[PlayFrameworkでCookieを試してみました](http://qiita.com/t-mochizuki/items/6498b040e8daefa5692c)のコードを流用します。

## ディレクトリ構造

使用したディレクトリ構造は下記のディレクトリ構造になります。

```
.
├── app
│   └── controllers
│       └── Tokyo.scala
├── build.sbt
├── conf
│   ├── application.conf
│   └── routes
└── project
    ├── build.properties
    └── plugins.sbt
```

## ファイル

まずは、build.sbtを見てみます。ここではプロジェクトを設定しています。

```build.sbt
libraryDependencies += cache
routesGenerator := InjectedRoutesGenerator

lazy val commonSettings = Seq(
  version := "0.1-SNAPSHOT",
  organization := "com.sandbox",
  scalaVersion := "2.11.6"
)

lazy val root = (project in file("."))
  .settings(commonSettings: _*)
  .enablePlugins(PlayScala)
```

キャシュを使うために、libraryDependencies += cacheの行を追加しました。また、DIを使うために、routesGenerator := InjectedRoutesGeneratorの行を追加しました。

つぎに、plugins.sbtを見てみます。ここではプラグインを指定します。

```plugins.sbt
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.4.2")
```

build.propertiesを見てみます。ここではsbtのバージョンを指定します。

```build.properties
sbt.version=0.13.8
```

routesを見てみます。ここではリクエストをコントローラのアクションに関連付けます。

``` routes
GET / controllers.Tokyo.user
```

application.confを見てみます。このファイルが存在しない場合、実行時エラーになります。

```application.conf
# conf/application.conf
```

Tokyo.scalaを見てみます。ここではコントローラを用意します。

```Tokyo.scala
package controllers

import play.api.mvc._
import play.api.cache.Cached
import javax.inject.Inject

class Tokyo @Inject() (cached: Cached) extends Controller {
  def user = cached("page") {
    Action { implicit request =>
      Ok(s"cache!")
    }
  }
}
```


実は、これは実行時エラーになります。



`You do not have an implicit Application in scope. If you want to bring the current running Application into context, just add import play.api.Play.current`というエラーメッセージに従い、`import play.api.Play.current`を追加すれば、実行時エラーを解消できます。


DIを使ってみたところ、実行時エラーになりませんでした。

## キャッシュするか？

Playサーバを起動するために、次のようなコマンドラインを実行します。

```
$ sbt run
```

その後、ブラウザで`localhost:9000`にアクセスします。初回なのでキャッシュがありません。レスポンスステータスは200になります。

![スクリーンショット 2015-08-27 2.06.46.png](https://qiita-image-store.s3.amazonaws.com/0/29884/0ab2c922-ae24-6449-10a4-c72d65858911.png)

⌘+Rなどでリロードすると、初回アクセス時にレスポンスデータをキャッシュしているのでレスポンスステータスが304になります。

![スクリーンショット 2015-08-27 2.09.42.png](https://qiita-image-store.s3.amazonaws.com/0/29884/8e0a1afe-b202-406d-0c1b-362cfee71cf1.png)

## 意味のないリクエストパラメータを追加したときにキャッシュを回避するか？

意味のないリクエストパラメータを追加したときにキャッシュを回避することを確認します。

確認は簡単です。ブラウザで`http://localhost:9000/?fb=tokyo`にアクセスします。すると、レスポンスステータスが200になります。

`http://localhost:9000/?abc=123`とか`http://localhost:9000/?tw=9ab`とか、意味のないリクエストパラメータを追加すればキャッシュを回避することができます。

## まとめ

Play cache APIを使って、キャッシュを試してみました。まず、キャッシュすることを確認して、意味のないリクエストパラメータを追加したときにキャッシュを回避することを確認しました。

## 余談

実は、この記事で紹介した方法では、サーバ側を修正してリロードするとブラウザ側に修正が反映されます。。

## 参照URL

- [Play Framework のデフォルトキャッシュが開発モードですぐ消えるのを解消する : mwSoft blog](http://blog.mwsoft.jp/article/70589384.html)
- [ScalaCache](https://www.playframework.com/documentation/2.4.2/ScalaCache)
- [CacheApi - play.api.cache.CacheApi](https://www.playframework.com/documentation/2.4.2/api/scala/index.html#play.api.cache.CacheApi)
- [ブラウザキャッシュのまとめ - Please Sleep](http://please-sleep.cou929.nu/browser-caching-tutorial-memo.html)