File Coverage

blib/lib/Plack/Middleware/Session.pm
Criterion Covered Total %
statement 69 76 90.7
branch 17 22 77.2
condition 5 6 83.3
subroutine 18 19 94.7
pod 3 10 30.0
total 112 133 84.2


line stmt bran cond sub pod time code
1             package Plack::Middleware::Session;
2 14     14   114561 use strict;
  14         55  
  14         333  
3 14     14   66 use warnings;
  14         32  
  14         548  
4              
5             our $VERSION = '0.33';
6             our $AUTHORITY = 'cpan:STEVAN';
7              
8 14     14   3756 use Plack::Util;
  14         58462  
  14         344  
9 14     14   76 use Scalar::Util;
  14         27  
  14         454  
10 14     14   4640 use Plack::Session::Cleanup;
  14         39  
  14         355  
11              
12 14     14   71 use parent 'Plack::Middleware';
  14         26  
  14         62  
13              
14 14         45 use Plack::Util::Accessor qw(
15             state
16             store
17 14     14   21823 );
  14         31  
18              
19             sub prepare_app {
20 76     76 1 21923 my $self = shift;
21              
22 76 100       177 $self->state( 'Cookie' ) unless $self->state;
23 76         822 $self->state( $self->inflate_backend('Plack::Session::State', $self->state) );
24 76         427 $self->store( $self->inflate_backend('Plack::Session::Store', $self->store) );
25             }
26              
27             sub inflate_backend {
28 152     152 0 595 my($self, $prefix, $backend) = @_;
29              
30 152 100 100     872 return $backend if defined $backend && Scalar::Util::blessed $backend;
31              
32 7         15 my @class;
33 7 100       20 push @class, $backend if defined $backend; # undef means the root class
34 7         14 push @class, $prefix;
35              
36 7         26 Plack::Util::load_class(@class)->new();
37             }
38              
39             sub call {
40 78     78 1 62011 my $self = shift;
41 78         114 my $env = shift;
42              
43 78         151 my($id, $session) = $self->get_session($env);
44 78 100 66     313 if ($id && $session) {
45 42         123 $env->{'psgix.session'} = $session;
46             } else {
47 36         83 $id = $self->generate_id($env);
48 36         106 $env->{'psgix.session'} = {};
49             }
50              
51 78         212 $env->{'psgix.session.options'} = { id => $id };
52              
53 78         265 my $res = $self->app->($env);
54 78     78   799 $self->response_cb($res, sub { $self->finalize($env, $_[0]) });
  78         87798  
55             }
56              
57             sub get_session {
58 78     78 0 136 my($self, $env) = @_;
59              
60 78 100       150 my $id = $self->state->extract($env) or return;
61 50 100       545 my $session = $self->store->fetch($id) or return;
62              
63 42         1000 return ($id, $session);
64             }
65              
66             sub generate_id {
67 36     36 0 68 my($self, $env) = @_;
68 36         84 $self->state->generate($env);
69             }
70              
71             sub commit {
72 70     70 0 122 my($self, $env) = @_;
73              
74 70         107 my $session = $env->{'psgix.session'};
75 70         96 my $options = $env->{'psgix.session.options'};
76              
77             my $end = sub {
78 70 50   70   143 return if $options->{no_store};
79 70         172 $self->store->store($options->{id}, $session);
80 70         201 };
81              
82 70 50       171 if (not $options->{late_store}) {
    0          
83 70         116 $end->();
84             } elsif ($env->{'psgix.cleanup'}) {
85 0         0 push @{$env->{'psgix.cleanup.handlers'}}, $end;
  0         0  
86             } else {
87 0         0 $env->{'psgix.session.cleanup'}
88             = Plack::Session::Cleanup->new($end);
89             }
90             }
91              
92             sub finalize {
93 78     78 0 155 my($self, $env, $res) = @_;
94              
95 78         140 my $session = $env->{'psgix.session'};
96 78         134 my $options = $env->{'psgix.session.options'};
97              
98 78 100       190 if ($options->{expire}) {
99 8         35 $self->expire_session($options->{id}, $res, $env);
100             } else {
101 70 50       183 $self->change_id($env) if $options->{change_id};
102 70         180 $self->commit($env);
103 70         3683 $self->save_state($options->{id}, $res, $env);
104             }
105             }
106              
107             sub change_id {
108 0     0 1 0 my($self, $env) = @_;
109              
110 0         0 my $options = $env->{'psgix.session.options'};
111              
112 0         0 $self->store->remove($options->{id});
113 0         0 $options->{id} = $self->generate_id($env);
114             }
115              
116             sub expire_session {
117 8     8 0 38 my($self, $id, $res, $env) = @_;
118 8         53 $self->store->remove($id);
119 8         180 $self->state->expire_session_id($id, $res, $env->{'psgix.session.options'});
120             }
121              
122             sub save_state {
123 70     70 0 177 my($self, $id, $res, $env) = @_;
124 70         153 $self->state->finalize($id, $res, $env->{'psgix.session.options'});
125             }
126              
127             1;
128              
129             __END__