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   90349 use strict;
  14         27  
  14         491  
3 14     14   63 use warnings;
  14         19  
  14         674  
4              
5             our $VERSION = '0.30';
6             our $AUTHORITY = 'cpan:STEVAN';
7              
8 14     14   5486 use Plack::Util;
  14         69024  
  14         378  
9 14     14   97 use Scalar::Util;
  14         39  
  14         599  
10 14     14   5797 use Plack::Session::Cleanup;
  14         48  
  14         422  
11              
12 14     14   74 use parent 'Plack::Middleware';
  14         22  
  14         82  
13              
14 14         54 use Plack::Util::Accessor qw(
15             state
16             store
17 14     14   30048 );
  14         50  
18              
19             sub prepare_app {
20 76     76 1 22778 my $self = shift;
21              
22 76 100       208 $self->state( 'Cookie' ) unless $self->state;
23 76         1415 $self->state( $self->inflate_backend('Plack::Session::State', $self->state) );
24 76         447 $self->store( $self->inflate_backend('Plack::Session::Store', $self->store) );
25             }
26              
27             sub inflate_backend {
28 152     152 0 522 my($self, $prefix, $backend) = @_;
29              
30 152 100 100     1046 return $backend if defined $backend && Scalar::Util::blessed $backend;
31              
32 7         11 my @class;
33 7 100       26 push @class, $backend if defined $backend; # undef means the root class
34 7         14 push @class, $prefix;
35              
36 7         36 Plack::Util::load_class(@class)->new();
37             }
38              
39             sub call {
40 78     78 1 81189 my $self = shift;
41 78         95 my $env = shift;
42              
43 78         158 my($id, $session) = $self->get_session($env);
44 78 100 66     334 if ($id && $session) {
45 42         99 $env->{'psgix.session'} = $session;
46             } else {
47 36         84 $id = $self->generate_id($env);
48 36         117 $env->{'psgix.session'} = {};
49             }
50              
51 78         200 $env->{'psgix.session.options'} = { id => $id };
52              
53 78         262 my $res = $self->app->($env);
54 78     78   938 $self->response_cb($res, sub { $self->finalize($env, $_[0]) });
  78         69275  
55             }
56              
57             sub get_session {
58 78     78 0 97 my($self, $env) = @_;
59              
60 78 100       163 my $id = $self->state->extract($env) or return;
61 50 100       673 my $session = $self->store->fetch($id) or return;
62              
63 42         1042 return ($id, $session);
64             }
65              
66             sub generate_id {
67 36     36 0 50 my($self, $env) = @_;
68 36         84 $self->state->generate($env);
69             }
70              
71             sub commit {
72 70     70 0 81 my($self, $env) = @_;
73              
74 70         84 my $session = $env->{'psgix.session'};
75 70         123 my $options = $env->{'psgix.session.options'};
76              
77             my $end = sub {
78 70 50   70   141 return if $options->{no_store};
79 70         183 $self->store->store($options->{id}, $session);
80 70         205 };
81              
82 70 50       161 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 119 my($self, $env, $res) = @_;
94              
95 78         122 my $session = $env->{'psgix.session'};
96 78         99 my $options = $env->{'psgix.session.options'};
97              
98 78 100       157 if ($options->{expire}) {
99 8         36 $self->expire_session($options->{id}, $res, $env);
100             } else {
101 70 50       191 $self->change_id($env) if $options->{change_id};
102 70         145 $self->commit($env);
103 70         9697 $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 21 my($self, $id, $res, $env) = @_;
118 8         29 $self->store->remove($id);
119 8         262 $self->state->expire_session_id($id, $res, $env->{'psgix.session.options'});
120             }
121              
122             sub save_state {
123 70     70 0 107 my($self, $id, $res, $env) = @_;
124 70         187 $self->state->finalize($id, $res, $env->{'psgix.session.options'});
125             }
126              
127             1;
128              
129             __END__