File Coverage

blib/lib/Dancer/Session/JSON.pm
Criterion Covered Total %
statement 73 73 100.0
branch 16 24 66.6
condition n/a
subroutine 18 18 100.0
pod 7 7 100.0
total 114 122 93.4


line stmt bran cond sub pod time code
1 1     1   355562 use strict;
  1         3  
  1         34  
2 1     1   6 use warnings;
  1         1  
  1         46  
3             package Dancer::Session::JSON;
4             BEGIN {
5 1     1   24 $Dancer::Session::JSON::VERSION = '0.001';
6             }
7             # ABSTRACT: JSON session backend for Dancer
8              
9 1     1   5 use Carp;
  1         8  
  1         71  
10 1     1   6 use base 'Dancer::Session::Abstract';
  1         1  
  1         940  
11              
12 1     1   2279 use JSON -convert_blessed_universally;
  1         14170  
  1         8  
13 1     1   316 use Fcntl ':flock';
  1         2  
  1         137  
14 1     1   5 use Dancer::Logger;
  1         3  
  1         23  
15 1     1   5 use Dancer::ModuleLoader;
  1         2  
  1         24  
16 1     1   5 use Dancer::Config 'setting';
  1         2  
  1         61  
17 1     1   5 use Dancer::FileUtils qw(path set_file_mode);
  1         1  
  1         716  
18              
19             # static
20              
21             my %session_dir_initialized;
22             my $json = JSON->new;
23              
24             sub init {
25 3     3 1 30 my $self = shift;
26              
27 3         21 $self->SUPER::init(@_);
28              
29             # default value for session_dir
30 3 100       601 defined setting('session_dir')
31             or setting( session_dir => path( setting('appdir'), 'sessions' ) );
32              
33 3         101 my $session_dir = setting('session_dir');
34 3 100       28 if ( ! exists $session_dir_initialized{$session_dir} ) {
35 2         6 $session_dir_initialized{$session_dir} = 1;
36              
37             # make sure session_dir exists
38 2 50       50 if ( ! -d $session_dir ) {
39 2 50       175 mkdir $session_dir
40             or croak "session_dir $session_dir cannot be created";
41             }
42              
43 2         16 Dancer::Logger::core("session_dir: $session_dir");
44             }
45             }
46              
47             # create a new session and return the newborn object
48             # representing that session
49             sub create {
50 3     3 1 1884 my ($class) = @_;
51              
52 3         27 my $self = Dancer::Session::JSON->new;
53 3         24 $self->flush;
54              
55 2         5 return $self;
56             }
57              
58             # deletes the dir cache
59             sub reset {
60 1     1 1 386 my ($class) = @_;
61 1         4 %session_dir_initialized = ();
62             }
63              
64             # Return the session object corresponding to the given id
65             sub retrieve {
66 6     6 1 3740 my $class = shift;
67 6         27 my $id = shift;
68 6         12 my $session_file = json_file($id);
69              
70 6 100       368 return unless -f $session_file;
71              
72 4 50       164 open my $fh, '+<', $session_file or die "Can't open '$session_file': $!\n";
73 4 50       31 flock $fh, LOCK_EX or die "Can't lock file '$session_file': $!\n";
74 4         4 my $json_data = do { local $/ = undef; <$fh>; };
  4         14  
  4         91  
75 4         46 my $content = $json->decode($json_data);
76 4 50       45 close $fh or die "Can't close '$session_file': $!\n";
77              
78 4         30 return bless $content => 'Dancer::Session::JSON';
79             }
80              
81             # instance
82             sub json_file {
83 12     12 1 43 my $id = shift;
84 12         35 return path( setting('session_dir'), "$id.json" );
85             }
86              
87             sub destroy {
88 1     1 1 741 my ($self) = @_;
89              
90 1         4 my $file = json_file( $self->id );
91 1         39 Dancer::Logger::core("trying to remove session file: $file");
92              
93 1 50       176 -f $file and unlink $file;
94             }
95              
96             sub flush {
97 4     4 1 429 my $self = shift;
98 4         15 my $session_file = json_file( $self->id );
99              
100 4 100       586 open my $fh, '>', $session_file or die "Can't open '$session_file': $!\n";
101 3 50       25 flock $fh, LOCK_EX or die "Can't lock file '$session_file': $!\n";
102 3         13 set_file_mode($fh);
103 3         419 print {$fh} $json->allow_blessed->convert_blessed->encode($self);
  3         145  
104 3 50       296 close $fh or die "Can't close '$session_file': $!\n";
105              
106 3         15 return $self;
107             }
108              
109             1;
110              
111              
112              
113             =pod
114              
115             =head1 NAME
116              
117             Dancer::Session::JSON - JSON session backend for Dancer
118              
119             =head1 VERSION
120              
121             version 0.001
122              
123             =head1 DESCRIPTION
124              
125             This module implements a session engine based on JSON files. Session are stored
126             in a I as JSON files. The idea behind this module was to provide a
127             transparent session storage for the developer.
128              
129             This backend is intended to be used in development environments, when looking
130             inside a session can be useful.
131              
132             It's not recommended to use this session engine in production environments.
133              
134             Typically you would want to use L for this, which comes
135             in core, but a demand for a faster-but-still-file-based session backend arose,
136             and thus you now have JSON. :)
137              
138             =head1 CONFIGURATION
139              
140             The setting B should be set to C in order to use this session
141             engine in a Dancer application.
142              
143             Files will be stored to the value of the setting C, whose default
144             value is C.
145              
146             Here is an example configuration that use this session engine and stores session
147             files in /tmp/dancer-sessions
148              
149             session: "JSON"
150             session_dir: "/tmp/dancer-sessions"
151              
152             =head1 SUBROUTINES/METHODS
153              
154             =head2 init
155              
156             Initializes the session backend.
157              
158             =head2 create
159              
160             Creates a new object, runs C and returns the object.
161              
162             =head2 flush
163              
164             Writes the session information to the session dir.
165              
166             =head2 retrieve
167              
168             Retrieves session information from the session dir.
169              
170             =head2 destroy
171              
172             Deletes session information from the session dir.
173              
174             =head2 reset
175              
176             Wipes the sessions directory, forcing a test for existence of the sessions
177             directory next time a session is created. It takes no argument.
178              
179             This is particulary useful if you want to remove the sessions directory on the
180             system where your app is running, but you want this session engine to continue
181             to work without having to restart your application.
182              
183             =head2 json_file
184              
185             Fetch the location of a json session file.
186              
187             =head1 SEE ALSO
188              
189             L - the original core development session backend.
190              
191             L - a faster in-memory core session backend.
192              
193             L - an encrypted cookie session backend, suitable
194             for production.
195              
196             =head1 AUTHOR
197              
198             Sawyer X
199              
200             =head1 COPYRIGHT AND LICENSE
201              
202             This software is copyright (c) 2011 by Sawyer X.
203              
204             This is free software; you can redistribute it and/or modify it under
205             the same terms as the Perl 5 programming language system itself.
206              
207             =cut
208              
209              
210             __END__