File Coverage

blib/lib/Mojolicious/Plugin/CSPHeader.pm
Criterion Covered Total %
statement 15 33 45.4
branch 3 18 16.6
condition 0 3 0.0
subroutine 3 3 100.0
pod 1 1 100.0
total 22 58 37.9


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::CSPHeader;
2 1     1   678 use Mojo::Base 'Mojolicious::Plugin';
  1         3  
  1         7  
3              
4             our $VERSION = '0.05';
5              
6             sub register {
7 1     1 1 45 my ($self, $app, $conf) = @_;
8              
9 1         6 my @directives = qw/base-uri block-all-mixed-content connect-src default-src font-src form-action frame-ancestors frame-src img-src manifest-src media-src object-src plugin-types report-to sandbox script-src strict-dynamic style-src upgrade-insecure-requests worker-src/;
10 1         2 my @deprecated = qw/child-src referrer report-uri/;
11 1         2 my @experimental = qw/disown-opener navigation-to report-sample require-sri-for/;
12              
13 1         3 for my $key (@deprecated) {
14 3 50       10 $app->log->info("You're using a deprecated CSP directive: $key") if $conf->{directives}->{$key};
15             }
16 1         3 for my $key (@experimental) {
17 4 50       9 $app->log->info("You're using an experimental CSP directive: $key") if $conf->{directives}->{$key};
18             }
19              
20             $app->hook(before_dispatch => sub {
21 2     2   25963 my $c = shift;
22              
23 2 50       8 if ($conf->{csp}) {
24 2         9 return $c->res->headers->content_security_policy($conf->{csp});
25             }
26              
27 0 0 0       if ($conf->{directives} || $conf->{extra}) {
28 0           my @csp;
29 0           for my $key (@directives, @deprecated, @experimental) {
30 0 0         if ($conf->{directives}->{$key}) {
31 0 0         if (ref($conf->{directives}->{$key}) eq 'HASH') {
32 0           my $value = $conf->{directives}->{$key}->{base};
33 0 0         if ($conf->{directives}->{$key}->{ws}) {
34 0 0         my $url = $c->req->url->to_abs
35             ->path('/')
36             ->scheme(($c->req->url->protocol =~ m/https|wss/) ? 'wss' : 'ws')
37             ->to_string;
38 0           $url =~ s#/$##;
39 0           $value .= ' '.$url;
40             }
41 0           push @csp, "$key ".$value;
42             } else {
43 0           push @csp, "$key ".$conf->{directives}->{$key};
44             }
45             }
46             }
47              
48 0 0         if ($conf->{extra}) {
49 0           for my $key (keys %{$conf->{extra}}) {
  0            
50 0           push @csp, "$key ".$conf->{extra}->{$key};
51             }
52             }
53              
54 0           my $csp_header = join('; ', @csp);
55              
56 0           return $c->res->headers->content_security_policy($csp_header);
57             }
58 1         11 });
59             }
60              
61             1;
62             __END__