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   81640 use strict;
  14         27  
  14         491  
3 14     14   64 use warnings;
  14         22  
  14         692  
4              
5             our $VERSION = '0.29';
6             our $AUTHORITY = 'cpan:STEVAN';
7              
8 14     14   5467 use Plack::Util;
  14         69082  
  14         356  
9 14     14   88 use Scalar::Util;
  14         42  
  14         580  
10 14     14   5476 use Plack::Session::Cleanup;
  14         66  
  14         462  
11              
12 14     14   76 use parent 'Plack::Middleware';
  14         21  
  14         83  
13              
14 14         57 use Plack::Util::Accessor qw(
15             state
16             store
17 14     14   29581 );
  14         43  
18              
19             sub prepare_app {
20 76     76 1 24470 my $self = shift;
21              
22 76 100       201 $self->state( 'Cookie' ) unless $self->state;
23 76         1455 $self->state( $self->inflate_backend('Plack::Session::State', $self->state) );
24 76         460 $self->store( $self->inflate_backend('Plack::Session::Store', $self->store) );
25             }
26              
27             sub inflate_backend {
28 152     152 0 528 my($self, $prefix, $backend) = @_;
29              
30 152 100 100     1034 return $backend if defined $backend && Scalar::Util::blessed $backend;
31              
32 7         11 my @class;
33 7 100       21 push @class, $backend if defined $backend; # undef means the root class
34 7         9 push @class, $prefix;
35              
36 7         32 Plack::Util::load_class(@class)->new();
37             }
38              
39             sub call {
40 78     78 1 59464 my $self = shift;
41 78         87 my $env = shift;
42              
43 78         159 my($id, $session) = $self->get_session($env);
44 78 100 66     326 if ($id && $session) {
45 42         85 $env->{'psgix.session'} = $session;
46             } else {
47 36         98 $id = $self->generate_id($env);
48 36         128 $env->{'psgix.session'} = {};
49             }
50              
51 78         195 $env->{'psgix.session.options'} = { id => $id };
52              
53 78         251 my $res = $self->app->($env);
54 78     78   997 $self->response_cb($res, sub { $self->finalize($env, $_[0]) });
  78         78231  
55             }
56              
57             sub get_session {
58 78     78 0 96 my($self, $env) = @_;
59              
60 78 100       206 my $id = $self->state->extract($env) or return;
61 50 100       654 my $session = $self->store->fetch($id) or return;
62              
63 42         1127 return ($id, $session);
64             }
65              
66             sub generate_id {
67 36     36 0 51 my($self, $env) = @_;
68 36         88 $self->state->generate($env);
69             }
70              
71             sub commit {
72 70     70 0 96 my($self, $env) = @_;
73              
74 70         93 my $session = $env->{'psgix.session'};
75 70         83 my $options = $env->{'psgix.session.options'};
76              
77             my $end = sub {
78 70 50   70   138 return if $options->{no_store};
79 70         173 $self->store->store($options->{id}, $session);
80 70         226 };
81              
82 70 50       153 if (not $options->{late_store}) {
    0          
83 70         107 $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 118 my($self, $env, $res) = @_;
94              
95 78         111 my $session = $env->{'psgix.session'};
96 78         103 my $options = $env->{'psgix.session.options'};
97              
98 78 100       157 if ($options->{expire}) {
99 8         39 $self->expire_session($options->{id}, $res, $env);
100             } else {
101 70 50       160 $self->change_id($env) if $options->{change_id};
102 70         139 $self->commit($env);
103 70         11830 $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 22 my($self, $id, $res, $env) = @_;
118 8         27 $self->store->remove($id);
119 8         273 $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         240 $self->state->finalize($id, $res, $env->{'psgix.session.options'});
125             }
126              
127             1;
128              
129             __END__