Skip to content
Browse files

remake Plugin::Session.

  • Loading branch information...
1 parent 71c6e32 commit f6c9a593a8be888293dda7c8cc5f3bcc9c247530 @nekokak committed Oct 27, 2009
View
138 lib/Kamui/Plugin/Session.pm
@@ -1,20 +1,148 @@
package Kamui::Plugin::Session;
use Kamui;
use base 'Kamui::Plugin';
-use HTTP::Session;
+sub do_finalize { 1 }
sub register_method {
+{
session => sub {
my $c = shift;
- HTTP::Session->new(
- request => $c->req,
- %{$c->conf->{plugins}->{session}}
- );
+ Kamui::Plugin::Session::Backend->new($c);
},
};
}
+package Kamui::Plugin::Session::Backend;
+use Kamui;
+use Time::HiRes;
+use Digest::SHA1;
+
+sub new {
+ my ($class, $c) = @_;
+
+ my $conf = $c->conf->{plugins}->{session} or die 'no session configuration!';
+
+ my $self = bless {
+ c => $c,
+ session_id => '',
+ session_data => +{},
+ session_updated => 0,
+ sid_length => 32,
+ state => undef,
+ store => undef,
+ conf => $conf,
+ }, $class;
+
+ $self->_setup;
+
+ $self;
+}
+
+sub _setup {
+ my $self = shift;
+
+ $self->_setup_state;
+ $self->_setup_store;
+ $self->_load_session;
+}
+
+sub _setup_state {
+ my $self = shift;
+
+ my $pkg = $self->{conf}->{state}->{class};
+ $self->{c}->app->load_class($pkg);
+ $self->{state} = $pkg->new(
+ req => $self->{c}->req,
+ %{$self->{conf}->{state}->{option}}
+ );
+}
+
+sub _setup_store {
+ my $self = shift;
+
+ my $pkg = $self->{conf}->{store}->{class};
+ $self->{c}->app->load_class($pkg);
+ $self->{store} = $pkg->new(%{$self->{conf}->{store}->{option}});
+}
+
+sub _load_session {
+ my $self = shift;
+
+ if (my $session_id = $self->_get_session_id) {
+ $self->_set_session_id($session_id);
+ $self->{session_data} = $self->_get_session_data($session_id);
+ } else {
+ $self->_initialize_session_data;
+ }
+}
+
+sub get {
+ my ($self, $key) = @_;
+ my $data = $self->{session_data} or return;
+ $self->{session_updated}=1;
+ $data->{ $key };
+}
+
+sub set {
+ my ($self, $key, $value) = @_;
+ $self->{session_updated}=1;
+ $self->{session_data}->{ $key } = $value;
+}
+
+sub remove {
+ my ($self, $key) = @_;
+ return unless $self->{session_data};
+ $self->{session_updated}=1;
+ delete $self->{session_data}->{ $key };
+}
+
+sub regenerate {
+ my ($self) = @_;
+
+ # ignore if session does not exists
+ return unless $self->{session_id};
+
+ my $session_data = $self->{session_data};
+ $self->_remove_session_data($self->{session_id});
+
+ $self->_initialize_session_data;
+ $self->_set_session_data($self->{session_id} => $session_data);
+ $self->{session_data} = $session_data;
+}
+
+sub finalize {
+ my ($self, $res) = @_;
+
+ if ($self->{session_updated} and my $sid = $self->{session_id}) {
+ $self->_state->finalize($res);
+ $self->_set_session_data( $sid, $self->{session_data} );
+ }
+}
+
+sub _initialize_session_data {
+ my $self = shift;
+
+ my $unique = ( [] . rand() );
+ $self->_set_session_id(
+ substr( Digest::SHA1::sha1_hex( Time::HiRes::gettimeofday() . $unique ), 0, $self->{sid_length} )
+ );
+ $self->{session_data} = +{};
+}
+
+# State
+sub _get_session_id { $_[0]->{state}->get_session_id }
+sub _set_session_id {
+ my ($self, $sid) = @_;
+ $self->{session_id} = $sid;
+ $self->{state}->set_session_id($sid);
+}
+sub _remove_session_id { $_[0]->{state}->remove_session_id($_[0]->{session_id}) }
+
+# Store
+sub _get_session_data { $_[0]->{store}->get_session_data($_[1]) }
+sub _set_session_data { $_[0]->{store}->set_session_data }
+sub _remove_session_data { $_[0]->{store}->remove_session_data }
+
1;
View
9 lib/Kamui/Plugin/Session/State.pm
@@ -0,0 +1,9 @@
+package Kamui::Plugin::Session::State;
+use Kamui;
+
+sub get_session_id { die 'this method is abstract !' }
+sub set_session_id { die 'this method is abstract !' }
+sub remove_session_id { die 'this method is abstract !' }
+
+1;
+
View
63 lib/Kamui/Plugin/Session/State/Cookie.pm
@@ -0,0 +1,63 @@
+package Kamui::Plugin::Session::State::Cookie;
+use Kamui;
+use base 'Kamui::Plugin::Session::State';
+
+sub new {
+ my $class = shift;
+
+ bless +{
+ req => undef,
+ cookie_name => 'kamui_sid',
+ cookie_domain => '',
+ cookie_path => '',
+ cookie_expires => '+1d',
+ cookie_secure => 0,
+ update_cookie => +{},
+ @_
+ }, $class,
+}
+
+sub get_session_id {
+ my $self = shift;
+
+ my $req = $self->{req};
+
+ if ( my $cookie = $req->cookies->{ $self->{cookie_name} } ) {
+ my $sid = $cookie->value;
+ return $sid if $sid;
+ }
+
+ return;
+}
+sub set_session_id {
+ my ($self, $sid) = @_;
+ $self->{update_cookie} = $self->make_cookie($sid);
+}
+sub remove_session_id {
+ my ($self, $sid) = @_;
+ $self->{update_cookie} = $self->make_cookie( $sid, { expires => 0 } );
+}
+
+sub make_cookie {
+ my ($self, $sid, $attrs) = @_;
+
+ my $cookie = {
+ value => $sid,
+ expires => $self->{cookie_expires},
+ secure => $self->{cookie_secure},
+ $self->{cookie_domain} ? (domain => $self->{cookie_domain}) : (),
+ $self->{cookie_path} ? (path => $self->{cookie_path}) : (),
+ %{ $attrs || {} },
+ };
+}
+
+sub finalize {
+ my ($self, $res) = @_;
+
+ if (my $cookie = $self->{update_cookie}) {
+ $res->cookies->{ $self->{cookie_name} } = $cookie;
+ }
+}
+
+1;
+
View
34 lib/Kamui/Plugin/Session/State/MobileAttributeID.pm
@@ -0,0 +1,34 @@
+package Kamui::Plugin::Session::State::MobileAttributeID;
+use Kamui;
+use base 'Kamui::Plugin::Session::State';
+
+sub new {
+ my $class = shift;
+ my $c = shift;
+
+ bless +{
+ @_
+ }, $class,
+}
+
+sub get_session_id {
+ my $self = shift;
+
+ my $req = $self->{req};
+
+ return;
+}
+sub set_session_id {
+ my ($self, $sid) = @_;
+}
+sub remove_session_id {
+ my ($self, $sid) = @_;
+}
+
+sub finalize {
+ my ($self, $res) = @_;
+
+}
+
+1;
+
View
9 lib/Kamui/Plugin/Session/Store.pm
@@ -0,0 +1,9 @@
+package Kamui::Plugin::Session::Store;
+use Kamui;
+
+sub get_session_data { die 'this method is abstract !'}
+sub set_session_data { die 'this method is abstract !'}
+sub remove_session_data { die 'this method is abstract !'}
+
+1;
+
View
31 lib/Kamui/Plugin/Session/Store/Memory.pm
@@ -0,0 +1,31 @@
+package Kamui::Plugin::Session::Store::Memory;
+use Kamui;
+use base 'Kamui::Plugin::Session::Store';
+
+my %session = ();
+
+sub new {
+ my ($class, %args) = @_;
+ bless \%args, $class;
+}
+
+sub get_session_data {
+ my ($self, $key) = @_;
+
+ if (my $session = $session{$key}) {
+ return $session;
+ }
+}
+
+sub set_session_data {
+ my ($self, $key, $value) = @_;
+ $session{$key} = $value;
+}
+
+sub remove_session_data {
+ my ($self, $key) = @_;
+ delete $session{$key};
+}
+
+1;
+
View
6 t/030_plugin/session.t → t/030_plugin/session/base.t
@@ -14,15 +14,17 @@ describe 'plugin tests' => run {
my $env = +{
REQUEST_METHOD => 'GET',
SCRIPT_NAME => '/',
- QUERY_STRING => 'p=query',
};
my $c = Kamui::Web::Context->new(
env => $env,
app => 'Mock::Web::Handler',
conf => container('conf'),
);
- isa_ok $c->session, 'HTTP::Session';
+ my $session = $c->session;
+ isa_ok $session, 'Kamui::Plugin::Session::Backend';
+ isa_ok $session->{state}, 'Kamui::Plugin::Session::State::Cookie';
+ isa_ok $session->{store}, 'Kamui::Plugin::Session::Store::Memory';
};
};
View
12 t/config.pl
@@ -27,11 +27,15 @@
},
};
-use HTTP::Session::Store::OnMemory;
-use HTTP::Session::State::Null;
$conf->{plugins}->{session} = +{
- store => HTTP::Session::Store::OnMemory->new(),
- state => HTTP::Session::State::Null->new(),
+ state => +{
+ class => 'Kamui::Plugin::Session::State::Cookie',
+ option => +{},
+ },
+ store => +{
+ class => 'Kamui::Plugin::Session::Store::Memory',
+ option => +{},
+ },
};
$conf->{plugins}->{mobile}->{css_filter} = +{

0 comments on commit f6c9a59

Please sign in to comment.
Something went wrong with that request. Please try again.