File Coverage

blib/lib/Dancer2/Core/Cookie.pm
Criterion Covered Total %
statement 45 46 97.8
branch 18 24 75.0
condition 2 3 66.6
subroutine 11 11 100.0
pod 0 2 0.0
total 76 86 88.3


line stmt bran cond sub pod time code
1             package Dancer2::Core::Cookie;
2             # ABSTRACT: A cookie representing class
3             $Dancer2::Core::Cookie::VERSION = '2.0.1';
4 161     161   400628 use Moo;
  161         16795  
  161         1265  
5 161     161   96648 use URI::Escape;
  161         85236  
  161         15614  
6 161     161   2246 use Dancer2::Core::Types;
  161         430  
  161         1836  
7 161     161   2315101 use Dancer2::Core::Time;
  161         702  
  161         7690  
8 161     161   1537 use Carp 'croak';
  161         460  
  161         13028  
9 161     161   1973 use Ref::Util qw< is_arrayref is_hashref >;
  161         1364  
  161         11496  
10 161     161   1230 use overload '""' => \&_get_value;
  161         338  
  161         1977  
11              
12             BEGIN {
13             my $try_xs =
14             exists($ENV{PERL_HTTP_XSCOOKIES}) ? !!$ENV{PERL_HTTP_XSCOOKIES} :
15             exists($ENV{PERL_ONLY}) ? !$ENV{PERL_ONLY} :
16 161 50   161   43370 1;
    50          
17              
18 161         489 my $use_xs = 0;
19 161 50       865 $try_xs and eval {
20 161         88240 require HTTP::XSCookies;
21 161         114594 $use_xs++;
22             };
23 161 50       632 if ( $use_xs ) {
24 161         830 *to_header = \&xs_to_header;
25             }
26             else {
27 0         0 *to_header = \&pp_to_header;
28             }
29 161 50       124295 *_USE_XS = $use_xs ? sub () { !!1 } : sub () { !!0 };
30             }
31              
32             sub xs_to_header {
33 96     96 0 3615 my $self = shift;
34              
35             # HTTP::XSCookies can't handle multi-value cookies.
36 96 100       182 return $self->pp_to_header(@_) if @{[ $self->value ]} > 1;
  96         2554  
37              
38 95         2148 return HTTP::XSCookies::bake_cookie(
39             $self->name,
40             { value => $self->value,
41             path => $self->path,
42             domain => $self->domain,
43             expires => $self->expires,
44             httponly => $self->http_only,
45             secure => $self->secure,
46             samesite => $self->same_site,
47             }
48             );
49             }
50              
51             sub pp_to_header {
52 9     9 0 288 my $self = shift;
53              
54 9         284 my $value = join( '&', map uri_escape($_), $self->value );
55 9   66     513 my $no_httponly = defined( $self->http_only ) && $self->http_only == 0;
56              
57 9         479 my @headers = $self->name . '=' . $value;
58 9 50       249 push @headers, "Path=" . $self->path if $self->path;
59 9 100       435 push @headers, "Expires=" . $self->expires if $self->expires;
60 9 100       282 push @headers, "Domain=" . $self->domain if $self->domain;
61 9 100       283 push @headers, "SameSite=" . $self->same_site if $self->same_site;
62 9 100       275 push @headers, "Secure" if $self->secure;
63 9 100       79 push @headers, 'HttpOnly' unless $no_httponly;
64              
65 9         77 return join '; ', @headers;
66             }
67              
68             has value => (
69             is => 'rw',
70             isa => ArrayRef,
71             required => 0,
72             coerce => sub {
73             my $value = shift;
74             my @values =
75             is_arrayref($value) ? @$value
76             : is_hashref($value) ? %$value
77             : ($value);
78             return [@values];
79             },
80             );
81              
82             around value => sub {
83             my $orig = shift;
84             my $self = shift;
85             my $array = $orig->( $self, @_ );
86             return wantarray ? @$array : $array->[0];
87             };
88              
89             # this is only for overloading; need a real sub to refer to, as the Moose
90             # attribute accessor won't be available at that point.
91 88     88   2358 sub _get_value { shift->value }
92              
93             has name => (
94             is => 'rw',
95             isa => Str,
96             required => 1,
97             );
98              
99             has expires => (
100             is => 'rw',
101             isa => Str,
102             required => 0,
103             coerce => sub {
104             Dancer2::Core::Time->new( expression => $_[0] )->gmt_string;
105             },
106             );
107              
108             has domain => (
109             is => 'rw',
110             isa => Str,
111             required => 0,
112             );
113              
114             has path => (
115             is => 'rw',
116             isa => Str,
117             default => sub {'/'},
118             predicate => 1,
119             );
120              
121             has secure => (
122             is => 'rw',
123             isa => Bool,
124             required => 0,
125             default => sub {0},
126             );
127              
128             has http_only => (
129             is => 'rw',
130             isa => Bool,
131             required => 0,
132             default => sub {1},
133             );
134              
135             has same_site => (
136             is => 'rw',
137             isa => Enum[qw[Strict Lax None]],
138             required => 0,
139             );
140              
141             1;
142              
143             __END__