File Coverage

blib/lib/Kelp/Module/Storage/Abstract.pm
Criterion Covered Total %
statement 27 27 100.0
branch 2 4 50.0
condition 2 5 40.0
subroutine 4 4 100.0
pod 1 1 100.0
total 36 41 87.8


line stmt bran cond sub pod time code
1             package Kelp::Module::Storage::Abstract;
2             $Kelp::Module::Storage::Abstract::VERSION = '1.00';
3 1     1   589376 use Kelp::Base 'Kelp::Module';
  1         2  
  1         5  
4 1     1   794 use Storage::Abstract;
  1         431163  
  1         44  
5 1     1   717 use Plack::App::Storage::Abstract;
  1         11597  
  1         519  
6              
7             sub build
8             {
9 1     1 1 160 my ($self, %args) = @_;
10 1         5 my $app = $self->app;
11              
12 1   50     9 my $routes = delete $args{public_routes} // {};
13             require Kelp::Module::Storage::Abstract::KelpExtensions
14 1 50       709 if delete $args{kelp_extensions};
15              
16 1         16 my $storage = Storage::Abstract->new(%args);
17              
18 1         136927 foreach my $key (keys %$routes) {
19 1         5 my $mapping = $routes->{$key};
20 1         2 my $this_storage = $storage;
21              
22             # key will have />file appended
23             # name will be adjusted so that /public/path key becomes storage_public_path
24 1         3 my $name = $key;
25 1         12 $name =~ s{^/+|/+$}{}g;
26 1         3 $name =~ s{/+}{_}g;
27 1         10 $name = "storage_$name";
28 1         7 $key =~ s{/?$}{/>file};
29              
30 1 50 33     9 if ($mapping && $mapping ne '/') {
31 1         37 $this_storage = Storage::Abstract->new(
32             driver => 'subpath',
33             source => $storage,
34             subpath => $mapping,
35             );
36             }
37              
38 1         105650 my $plack_app = Plack::App::Storage::Abstract->new(
39             storage => $this_storage,
40             encoding => $app->charset,
41             );
42              
43 1         204 $app->add_route(
44             $key => {
45             to => $plack_app->to_app,
46             name => $name,
47             psgi => 1,
48             }
49             );
50             }
51              
52 1         6393 $self->register(storage => $storage);
53             }
54              
55             1;
56              
57             __END__
58              
59             =head1 NAME
60              
61             Kelp::Module::Storage::Abstract - Abstract file storage for Kelp
62              
63             =head1 SYNOPSIS
64              
65             # in the configuration
66             modules => [qw(Storage::Abstract)],
67             modules_init => {
68             'Storage::Abstract' => {
69             driver => 'directory',
70             directory => '/path/to/rootdir',
71             public_routes => {
72             # map URL /public to the root of the storage
73             '/public' => '/',
74             },
75             kelp_extensions => 1,
76             },
77             },
78              
79             =head1 DESCRIPTION
80              
81             This module adds L<Storage::Abstract> instance to Kelp, along with a static
82             file server functionality and some file-related utility methods.
83              
84             =head1 METHODS INTRODUCED TO KELP
85              
86             =head2 storage
87              
88             $obj = $app->storage
89              
90             This is a L<Storage::Abstract> object constructed using the module configuration.
91              
92             =head1 CONFIGURATION
93              
94             Most configuration values will be used to construct the underlying storage
95             object. Consult L<Storage::Abstract> and its drivers documentation for details.
96              
97             Two special flags exist:
98              
99             =over
100              
101             =item * C<public_routes>
102              
103             This key, if passed, should be a hash reference where each key is a base route
104             and each value is a storage path from which the files will be served. If you write:
105              
106             public_routes => {
107             '/public' => '/',
108             },
109              
110             Then it will be possible to access to all files from your storage through
111             C</public> route. A L<Plack::App::Storage::Abstract> instance will be set up on
112             each of these routes.
113              
114             This route will be given a name corresponding to its url, with slashes replaced
115             with underscores and C<storage_> prepended. So the route above will be named
116             C<storage_public>. You may use it to build URLs for this route - the additional
117             path of the file must be passed as a C<file> placeholder, so for example:
118              
119             my $url = $app->url_for(storage_public => (file => 'my/file'));
120              
121             =item * C<kelp_extensions>
122              
123             This key will enable additional extensions to L<Kelp::Response>. It will add a
124             new method to it called C<render_file>. This method will take files from your
125             storage and render them much like L<Plack::App::Storage::Abstract> does:
126              
127             $app->add_route('/serve_file' => sub {
128             my $app = shift;
129             $app->res->render_file('/file/path');
130             });
131              
132             Note that it modifies the base L<Kelp::Response> class and not create a subclass.
133              
134             =back
135              
136             =head1 SEE ALSO
137              
138             L<Kelp>
139              
140             L<Storage::Abstract>
141              
142             =head1 AUTHOR
143              
144             Bartosz Jarzyna E<lt>bbrtj.pro@gmail.comE<gt>
145              
146             =head1 COPYRIGHT AND LICENSE
147              
148             Copyright (C) 2024 by Bartosz Jarzyna
149              
150             This library is free software; you can redistribute it and/or modify
151             it under the same terms as Perl itself.
152