Armadilloフォーラム

lightttpd キャッシュ制御

shsuga

2016年6月22日 18時11分

お世話になっております。
初めて投稿いたします菅と申します。
よろしくお願いいたします。

atmarkdist標準のlighttpd を利用してWEBによる本体設定を実装していますが、
以下の問題で苦慮しています。

【障害内容】
設定変更・再起動後にWEBブラウザーから設定を再表示すると、変更内容が反映されない。

【原因】
ブラウザーがヘッダに、If-Modified-Since を指定して呼び出すと、httpd は 304 Not Modified
で応答する。時間は設定していないので、電源立ち上げ後は、毎回1970年1月1日に初期化される。
NTPによる時間設定が可能であるが、お客様の都合で設定していない。

【期待する動作】
If-Modified-Sinceヘッダを指定されて、時間が古くても必ず、200 OK で応答する。
ブラウザーへの応答に Last-Modified を返さなければ、ブラウザーは If-Modified-Since
を付けてこないらしい事もわかりましたので、Last-Modified を返却しない方法でも結構です。

【環境】
armadillo-420
atmark-dist-20150318
lighttpd-1.4.13 (ssl) Build-Date: Jul 27 2015 10:31:11

以上、よろしくお願いいたします。


コメント

shsuga

2016年6月23日 13時05分

斉藤さん、
コメント、ありがとうございます。
残念ながら、HTMLにキャッシュ禁止のタグを加えましたが、
相変わらず、問題は解決しませんでした。
但し、上記状態でネットワークトレースの解析はしていませんので、
一度確認してみます。

> 齊藤と申します
> 設定ページのHTMLを修正してキャッシュ禁止するのではダメなんでしょうか?
>
> たとえばこんな
> http://htak.hatenablog.com/entry/2013/06/20/213822

access.mihara

2016年6月23日 13時45分

株式会社ACCESS 三原と申します。

Web 開発の基礎を確認させていただけませんか?

1. ページは静的 HTML (*.html ファイル)ですか? CGI 等の動的ページですか?
2. もし静的 HTML だった場合、

> 設定変更・再起動後にWEBブラウザーから設定を再表示すると、変更内容が反映されない。

変更内容をどのような仕組みで反映させていますか? ファイル書き換えでしょうか?

CGI 等だとプログラムで Last-Modified ヘッダをつけるようコーディングしない限り Last-Modified ヘッダは送付されません。

おそらく静的 HTML ファイルを送信しているのでタイムスタンプから Last-Modified ヘッダが送付されているのだろうと想像します。この想像ははずれているでしょうか?

lighttpd で静的ファイル送信時に Last-Modified ヘッダを「付与しない」という方向で考えると、ネットを検索するに、絶望的です。海外の技術者掲示板で2件の質問が回答のないまま終わっています。

* https://redmine.lighttpd.net/boards/2/topics/1639
* http://serverfault.com/questions/195402/how-to-remove-response-header-i…

上記の回答としては、付与しないことはできないから mod_expire モジュールでページの有効期限を操作しろとあります。

mod_expire モジュールのマニュアル
https://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ModExpire

マニュアルのサンプルコードでは、ファイルの更新日時ではなくアクセス日時を基準にしてページの有効期限を設定しています。これしかできないでしょう。

access.mihara

2016年6月23日 13時52分

株式会社ACCESS 三原と申します。

申し訳ありません。英語掲示板を読み間違えました。

> lighttpd で静的ファイル送信時に Last-Modified ヘッダを「付与しない」という方向で考えると、ネットを検索するに、絶望的です。海外の技術者掲示板で2件の質問が回答のないまま終わっています。
>
> * https://redmine.lighttpd.net/boards/2/topics/1639
> * http://serverfault.com/questions/195402/how-to-remove-response-header-i…

下の掲示板の内容は "This won't necessarily remove the Last-Modified header, but the end result may be similar to what you are looking for:" (拙訳: Last-Modified ヘッダを削除する必要はなくて、あなたの希望に近いことはできる)でしたから、その次に掲載されたサンプルコードを lighttpd.conf に追加すれば目的にかなうのではないでしょうか。


expire.url = ("" => "modification" )
etag.use-inode = "disable"
etag.use-mtime = "disable"
etag.use-size = "disable"
static-file.etags = "disable"

shsuga

2016年6月23日 16時47分

三原さん、
有用な情報をありがとうございます。

該当ページですが、機器設定WEBページですので、基本的には静的ページですが、
実際の設定値を反映させるため、定期的に監視して、変更がある場合は更新しています。
また、設定値保存や機器リセットなどでCGIを使用しています。
現在、外出ですので明日、ご教示頂いた情報で確認してみます。
また、結果を投稿させていただきます。

以上、ありがとうございました。

> 株式会社ACCESS 三原と申します。
>
> Web 開発の基礎を確認させていただけませんか?
>
> 1. ページは静的 HTML (*.html ファイル)ですか? CGI 等の動的ページですか?
> 2. もし静的 HTML だった場合、
>
> > 設定変更・再起動後にWEBブラウザーから設定を再表示すると、変更内容が反映されない。
>
> 変更内容をどのような仕組みで反映させていますか? ファイル書き換えでしょうか?
>
> CGI 等だとプログラムで Last-Modified ヘッダをつけるようコーディングしない限り Last-Modified ヘッダは送付されません。
>
> おそらく静的 HTML ファイルを送信しているのでタイムスタンプから Last-Modified ヘッダが送付されているのだろうと想像します。この想像ははずれているでしょうか?
>
> lighttpd で静的ファイル送信時に Last-Modified ヘッダを「付与しない」という方向で考えると、ネットを検索するに、絶望的です。海外の技術者掲示板で2件の質問が回答のないまま終わっています。
>
> * https://redmine.lighttpd.net/boards/2/topics/1639
> * http://serverfault.com/questions/195402/how-to-remove-response-header-i…
>
> 上記の回答としては、付与しないことはできないから mod_expire モジュールでページの有効期限を操作しろとあります。
>
> mod_expire モジュールのマニュアル
> https://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ModExpire
>
> マニュアルのサンプルコードでは、ファイルの更新日時ではなくアクセス日時を基準にしてページの有効期限を設定しています。これしかできないでしょう。
>

shsuga

2016年6月27日 16時04分

結論から先に申し上げると、色々と試してみましたが、成功しませんでした。

mod_expire:
expire.url = ("" => "modification  0 senconds" )
expire.url = ("" => "modification  plus 1 senconds" )
※状況変わらず

etag に関しては、本バージョンでは設定項目が未サポートで、
WARNING: unknown config-key: static-file.etags (ignored) となります。

結局、lighttpd のソースを変更しました。
http-header-glue.c の 関数(http_response_handle_cachable)
If-Modified-Since の判断で、304 Not Modified にしている箇所(4か所)を
クリップしました。これで、304にはならなくなりました。

しかし、IEではまだ問題が解決しません。
IEのデフォルト設定では、HTTPコンテンツを返しているにも関わらずキャッシュを使用します。
インターネットオプションの[全般]-閲覧の履歴[設定]
インターネット一時ファイル-保存しているページの新しいバージョンがあるかどうかの確認の
○自動的に確認するを指定すると、意図した動作になりました。
デフォルト値は、「自動的に確認する」です。

このオプションは何かと確認すると、参考:https://support.microsoft.com/ja-jp/kb/263070
自動的に確認する (Internet Explorer 5 以降のみ) : [Internet Explorer を起動するごとに確認する] と同じですが、このオプションでは Web ページの動作の特徴を認識するアルゴリズムが使用されます。このオプションを使用すると、以前表示したことがあるページに戻ったときに、そのページが最後に表示されてから変更されたかどうかが、通常は確認されません。

要するにIEのデフォルト設定では、ページが更新されたかは確認せずに、キャッシュを利用するようです。

以上、コメントを頂きました皆様に感謝いたします。

shsuga

2016年6月27日 16時07分

ごめんなさい。訂正です。

意図した動作になったIEの設定は、
「ページを表示するごとに確認する 」 です。

失礼いたしました。
> 結論から先に申し上げると、色々と試してみましたが、成功しませんでした。
>
> mod_expire:
> expire.url = ("" => "modification  0 senconds" )
> expire.url = ("" => "modification  plus 1 senconds" )
> ※状況変わらず
>
> etag に関しては、本バージョンでは設定項目が未サポートで、
> WARNING: unknown config-key: static-file.etags (ignored) となります。
>
> 結局、lighttpd のソースを変更しました。
> http-header-glue.c の 関数(http_response_handle_cachable)
> If-Modified-Since の判断で、304 Not Modified にしている箇所(4か所)を
> クリップしました。これで、304にはならなくなりました。
>
> しかし、IEではまだ問題が解決しません。
> IEのデフォルト設定では、HTTPコンテンツを返しているにも関わらずキャッシュを使用します。
> インターネットオプションの[全般]-閲覧の履歴[設定]
> インターネット一時ファイル-保存しているページの新しいバージョンがあるかどうかの確認の
> ○自動的に確認するを指定すると、意図した動作になりました。
> デフォルト値は、「自動的に確認する」です。
>
> このオプションは何かと確認すると、参考:https://support.microsoft.com/ja-jp/kb/263070
> 自動的に確認する (Internet Explorer 5 以降のみ) : [Internet Explorer を起動するごとに確認する] と同じですが、このオプションでは Web ページの動作の特徴を認識するアルゴリズムが使用されます。このオプションを使用すると、以前表示したことがあるページに戻ったときに、そのページが最後に表示されてから変更されたかどうかが、通常は確認されません。
>
> 要するにIEのデフォルト設定では、ページが更新されたかは確認せずに、キャッシュを利用するようです。
>
> 以上、コメントを頂きました皆様に感謝いたします。
>
>
>
>
>
>
>

access.mihara

2016年6月27日 16時42分

株式会社ACCESS 三原と申します。

解決したところに書き込むのは失礼なことですが、lighttpd 側ではなく IE 側の挙動の説明に気になったところがございます。

> 要するにIEのデフォルト設定では、ページが更新されたかは確認せずに、キャッシュを利用するようです。

GET で取得したコンテンツが新鮮であるかどうかの判断は、IE が実装された当時の RFC 2616 には規定がありました。

RFC 2616
https://www.ietf.org/rfc/rfc2616.txt

> If none of Expires, Cache-Control: max-age, or Cache-Control: s-
> maxage (see section 14.9.3) appears in the response, and the response
> does not include other restrictions on caching, the cache MAY compute
> a freshness lifetime using a heuristic. The cache MUST attach Warning
> 113 to any response whose age is more than 24 hours if such warning
> has not already been added.
>
> Also, if the response does have a Last-Modified time, the heuristic
> expiration value SHOULD be no more than some fraction of the interval
> since that time. A typical setting of this fraction might be 10%.

"13.2.4 Expiration Calculations" より

Expires 等はないけれども Last-Modified ヘッダがある場合、Last-Modified から前回の GET までの経過時間からさらに 10% 増した時刻まではキャッシュを使うことを許可するという規定があったのです。

菅様の環境ですと Last-Modified が 1970 年だと思われますから、相当長くキャッシュを使用しても RFC 2616 が許可する範囲であったことをご理解いただきたく存じます。

この規定を回避するには GET レスポンスに Expires 等のヘッダを付与することになります。

よろしくお願いいたします。

shsuga

2016年7月1日 10時56分

追加情報です。

IEも含めて、対策の為、修正方法を変更しました。

強制的に304を返さない⇒×

変更内容:
Last-Modified 及び ETag を返さない様にする。
但し、副作用としてWEBアクセスのたびにページを返すので、
効率が悪いので、データ量の多いページへの適用は、
あまり、良くないかもしれません。

三原さん、追加の情報ありがとうございました。

以上、よろしくお願いいたします。