h2o の casper (cache-aware server-push) を有効にしていると、force reload したときでも push されなくなってしまって、だんだん混乱してきます。YAML を一時的に変えて再起動したりしていたのですが、自分以外にも影響が及ぶのでちょっとなんとかしました。

JS で h2o_casper クッキーを削除してからリロードする

最初に思いつく方法で手軽なやつです。以下のようなブックマークレットでリロードすると cookie がない状態からのリロードになります。

javascript:document.cookie="h2o_casper=; max-age=-1; path=/";location.reload(true);

h2o へパッチをあてて、force reload 時は常に h2o_casper を無視してプッシュさせる

force reload 時にブラウザはリクエストヘッダに Cache-Control: no-cache をつけるので (全てのブラウザかどうかわかりませんが)、その場合にはクッキーを無視して push します (set-cookie は吐かれます)

Cache-Control: no-cache とクライアントが宣言しているなら、casper も無効になっているのは正当ではないか?と思い実装しましたが、ほんとにそうか自信がないので、ひとまず自分のところでテストしています (このサーバには適用済み)。

diff --git a/lib/http2/connection.c b/lib/http2/connection.c
index 4395728..bc83829 100644
--- a/lib/http2/connection.c
+++ b/lib/http2/connection.c
@@ -1185,6 +1185,19 @@ static void push_path(h2o_req_t *src_req, const char *abspath, size_t abspath_le
                 src_stream->pull.casper_state = H2O_HTTP2_STREAM_CASPER_DISABLED;
                 return;
             }
+
+            /* disable casper (always push) when super-reloaded (cache-control is exactly matched to no-cache) */
+            if ( (header_index = h2o_find_header(&src_stream->req.headers, H2O_TOKEN_CACHE_CONTROL, -1)) != -1) {
+                h2o_header_t *header = src_stream->req.headers.entries + header_index;
+                if (h2o_lcstris(header->value.base, header->value.len, H2O_STRLIT("no-cache"))) {
+                    /* casper enabled for this request but ignore cookie */
+                    if (conn->casper == NULL)
+                        h2o_http2_conn_init_casper(conn, src_stream->req.hostconf->http2.casper.capacity_bits);
+                    src_stream->pull.casper_state = H2O_HTTP2_STREAM_CASPER_READY;
+                    break;
+                }
+            }
+
             /* casper enabled for this request */
             if (conn->casper == NULL)
                 h2o_http2_conn_init_casper(conn, src_stream->req.hostconf->http2.casper.capacity_bits);

mruby.handler でなんとかできないかと思いましたが、mruby 側の env に渡ってくる HTTP_COOKIE とかを書きかえても h2o 内部の処理には影響しないみたいなので無理そうでした。

  1. トップ
  2. tech
  3. h2o の casper を一時的に無効にする
▲ この日のエントリ