Windows Server 2012 では IIS 8。これが Windows Server 2012 R2 では IIS 8.5 になります。
なにが変わるかって? Static Content (静的コンテンツ) のキャッシュコントロールヘッダーがなんか変わるんですね-しょぼん。
今回はぐぐっても錯綜した情報が垣間見える、ASP.NET MVC における IIS の Static Content に関するキャッシュコントロールヘッダーの変更についてです。
何気に IIS でほげもげするのってあんまりまとまってないんですね。特にARR絡むと。
目次
- 目次
- Cache Control Header の確認
- IIS における Cache Control Header
- Custom Headers を設定する
- 拡張子に応じた Cacheの調整
- パスに応じたCache の調整
- ARRがあるときの web.config に注意
- まとめ
Cache Control Header の確認
Cache Control Header を確認するなら、Chrome や IE の開発者ツールを使うと楽でしょう。たぶんきっと。
F12 > Networkタブ > 適当なコンテンツ > Headers > Response Header
こんな感じで 応答ヘッダーが見えます。
Cache Control Header について
参考になるサイトです
ここを参考に、キャッシュさせたいもの、させたくないものにどんな Cache Control Header を設定すればいいのか頭を整理するといいでしょう。
IIS における Cache Control Header
web.config で設定しよう
IIS のCache Control Header ですが、通常は IIS全体(ApplicationHost.config) ではなく、サイト単位(web.config)で行うでしょう。
web.config でやらない理由がないですね。
IIS 8.5 における既定の Cache Control Header
まず Cache Control Header をそもそも付けるかどうかですが、これは System.Web ディレクティブ配下の httpRuntime 要素である sendCacheControlHeader
に boolean で指定します。
デフォルトは true で、そのままだと Cache Control Header に private が送信されます。つまり Cache されるかはブラウザの挙動に依存します。*1
これは reference Sourceに記述の通りですね。
今回の場合は、Cache Control Header は送信されないといけないのでそのままでいいでしょう。Private の削除など制御は別途行います。
なので、逆に以下のように system.web ディレクティブに sendCacheControlHeader="false"
がかかれていたらダメですね。
<system.web> <httpRuntime targetFramework="4.5" sendCacheControlHeader="false" /> </system.web>
Cloud Front での Cache など Origin のヘッダを尊重する Object Caching (CDN) の場合、むしろ false である方が望ましかったりするのですが今回はスルーで。
Custom Headers を設定する
View単位の設定
Cache Control Header をカスタムしたい。そんな時に、動的コンテンツ(ASP.NET でコードレベルでページごとに制御する) なら各View側のコードで指定すればできます
全View統一の設定
全Viewで統一の動きなら web.config です。
そこで使うのが、system.webServer ディレクティブ、 httpProtocolにある customHeaders
です。
customHeaders Element for httpProtocol [IIS Settings Schema] | Microsoft Learn
ここでは、任意のヘッダーを操作可能です。
例えば、X-Custom-Name で MyCustomValue
追加で返すならこうです。
<configuration> <system.webServer> <httpProtocol> <customHeaders> <add name="X-Custom-Name" value="MyCustomValue" /> </customHeaders> </httpProtocol> </system.webServer> </configuration>
customHeaders は、add, remove, clear の各attribute を持っているので、これを使って自由に操作できますす。
たとえば、Cache させたくないなら以下のように no-cache, no-store, must-revalidate を足せるでしょう。
Pragma をなくすなどいろんな説があるのですが.... いったん付けておきます。
<httpProtocol> <customHeaders> <add name="Cache-Control" value="no-cache, no-store, must-revalidate" /> <add name="Pragma" value="no-cache" /> <add name="Expires" value="-1" /> </customHeaders> </httpProtocol>
逆に Cache を常に有効にするなら、Cache-Control に、Public を付ければいいですね。Expiresなどで期限制御でしょう。
ただし、ここでやってしまうと全StaticContent に影響します。拡張子やパスごとに調整したくなったら 更に調整が必要でしょう。
拡張子に応じた Cacheの調整
Custom Headers で Cache 制御を書いたら、IIS reference の caching で調整ができます。逆にいうと Custom Headers で調整せずにやっても意味を成しません。
.asp の拡張子を対象にキャッシュ調整とかですね。
<configuration> <system.webServer> <caching enabled="true" enableKernelCache="true"> <profiles> <add extension=".asp" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange" /> </profiles> </caching> </system.webServer> </configuration>
同様に KernelCache が云々もできたりなんとか。
<configuration> <system.webServer> <caching enabled="true" enableKernelCache="true" maxCacheSize="1000" maxResponseSize="512000"/> </system.webServer> </configuration>
まぁでも、ひと昔ならともかく今は拡張子制御は微妙ですね…。
パスに応じたCache の調整
拡張子がによるキャッシュ制御が微妙とみなす理由の1つが、現在はパスで静的コンテンツを区切るパターンが多いからです。実際 minifyしてると拡張子がないファイルで展開することもありますしね。
そこで、全体ではCache Control を無効に *2しておいて、特定のパスだけ Cache を効かせる*3。といった、全体と一部パスで挙動を変化させる時に使えるのが location path=hogemoge
です。
iis - How to configure static content cache per folder and extension in IIS7? - Stack Overflow
パスごとにsystem.webServer
の調整ができたりするので、これを使えば パスごとの Cache Control Header を書き替えなおすこともできます。
例えば、全体では Cache Control を no-store, no-cache にしていても、 /static 配下のコンテンツはキャッシュしたいなら、全体に対するsystem.webServer ディレクティブの下に
<system.webServer> <httpProtocol> <customHeaders> <add name="Cache-Control" value="no-cache, no-store, must-revalidate" /> <add name="Pragma" value="no-cache" /> <add name="Expires" value="-1" /> </customHeaders> </httpProtocol> </system.webServer>
path を指定した記述を web.config で追加すればいけます。/static配下ならこうです。
<location path="static"> <system.webServer> <staticContent> <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="03:00:00" /> </staticContent> <httpProtocol> <customHeaders> <remove name="Cache-Control" /> <remove name="Pragma" /> <remove name="Expires" /> <add name="Cache-Control" value="public" /> </customHeaders> </httpProtocol> </system.webServer> </location>
これで IIS/ASP.NET を使っている時の Cache Control Header は制御できますね。
ARRがあるときの web.config に注意
ARR - Application Request Routing を使うと、IIS 自身で A WebSite から B WebSite にリダイレクト(URL 書き換え / プロキシ)を組んだりが簡単にできるようになります。
ARRを使うことで、ASP.NET の本体の前にいくつかのプロキシサイトを構成しておいて、「特定の状態の場合はアプリケーションまでルーティングさせない」などの構成が可能になります。結構神で素晴らしいわけです。
ProxySite - Application
ただし、ARR でルーティングするために作ったサイトはASP.NETなど本来やりたいWebサイトとは独立した Webサイトですよね。そのため、ASP.NET 本体などの前にProxy用のWebサイトがある時、ASP.NETの応答が外側のプロキシサイトのweb.config で上書かれるんですねー。はい注意。
なので、ASP.NET側で web.config を使って、あるいはコードでキャッシュ制御を書いても、プロキシサイトの web.config を調整しておかないといけません。
知らなくてはまりましたのです。
まとめ
web.config かわいいよ。web.config *4