読者です 読者をやめる 読者になる 読者になる

itochin2の日記(仮)

主に備忘録。Perl、MySQL、Unity、開発管理などについて情報を残していきたい。

HTTP::Session2でexpiresを設定する

perl

自動ログイン機能を実装していて、最後のログインから1ヶ月間有効っていうのをやりたかった。
フレームワークにAmon2を使っていて、セッションの保存先はmemcacheを指定。

http://search.cpan.org/~tokuhirom/HTTP-Session2/
http://search.cpan.org/~kazeburo/Cookie-Baker-0.03/lib/Cookie/Baker.pm

上記ドキュメントを参照しつつ、以下の様に実装したけど
expiresは有効にならなかった(ブラウザ落とすと消える)。

sub session {
    my $c = shift;
    
    if (!exists($c->{session})) {
        $c->{session} = HTTP::Session2::ServerStore->new(
            env       => $self->req->env,
            secret    => 'PyQwUiCRqxnzUxAxbhBfdAFTTaVVHJjn',
            get_store => sub {
                Cache::Memcached::Fast::Safe->new(
                    {
                        servers   => [ { address => 'localhost:11211' } ],
                        namespace => 'app_session',
                    },
                );
            },
            session_cookie => +{
                httponly => 1,
                secure   => 0,
                name     => 'has_session',
                path     => '/',
                expires  => '+1M',
            }
        );
    }
    return $c->{session};
}

原因

finalize_plack_responseがレスポンスヘッダにCookieをぶち込んでいるけど
こいつはCookie::Baker::bake_cookieを使っていない。

cookieのexpiresにはそもそもGMT形式の日付を渡す必要があって、
bake_cookieが’+1M’を良しなに加工してくれている。

そのbake_cookieを使っていないということは、cookieには謎の’+1M’という文字が
わたっているだけだったのだ。

修正

じゃあ一ヶ月後の日付をGMTにして渡せば解決ってことで、
以下のようにしたら、うまいこと行った。

sub session {
    my $c = shift;
    
    if (!exists($c->{session})) {
        $c->{session} = HTTP::Session2::ServerStore->new(
            env       => $self->req->env,
            secret    => 'PyQwUiCRqxnzUxAxbhBfdAFTTaVVHJjn',
            get_store => sub {
                Cache::Memcached::Fast::Safe->new(
                    {
                        servers   => [ { address => 'localhost:11211' } ],
                        namespace => 'app_session',
                    },
                );
            },
            session_cookie => +{
                httponly => 1,
                secure   => 0,
                name     => 'has_session',
                path     => '/',
            }
        );
        my $expires = time + (60*60*24*30);
        $c->{session}->session_cookie->{expires} = gmtime($expires);
    }
    return $c->{session};
}

Cookieのexpires形式がGMTだと知っていれば、もっと早く解決した気がする。