File Coverage

blib/lib/Dancer2/Core/Cookie.pm
Criterion Covered Total %
statement 48 49 97.9
branch 19 26 73.0
condition 2 3 66.6
subroutine 12 12 100.0
pod 1 3 33.3
total 82 93 88.1


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.1.0';
4 166     166   402684 use Moo;
  166         17203  
  166         1365  
5 166     166   108584 use URI::Escape;
  166         86434  
  166         14827  
6 166     166   2190 use Dancer2::Core::Types;
  166         416  
  166         1794  
7 166     166   2300243 use Dancer2::Core::Time;
  166         699  
  166         7953  
8 166     166   1434 use Carp 'croak';
  166         361  
  166         13060  
9 166     166   2736 use Ref::Util qw< is_arrayref is_hashref >;
  166         1872  
  166         12622  
10 166     166   1267 use overload '""' => \&_get_value;
  166         386  
  166         2094  
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 166 50   166   47312 1;
    50          
17              
18 166         407 my $use_xs = 0;
19 166 50       902 $try_xs and eval {
20 166         91197 require HTTP::XSCookies;
21 166         120511 $use_xs++;
22             };
23 166 50       743 if ( $use_xs ) {
24 166         875 *to_header = \&xs_to_header;
25             }
26             else {
27 0         0 *to_header = \&pp_to_header;
28             }
29 166 50       137527 *_USE_XS = $use_xs ? sub () { !!1 } : sub () { !!0 };
30             }
31              
32             sub xs_to_header {
33 99     99 0 3124 my $self = shift;
34              
35             # HTTP::XSCookies can't handle multi-value cookies.
36 99 100       173 return $self->pp_to_header(@_) if @{[ $self->value ]} > 1;
  99         2202  
37              
38 98         1906 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 290 my $self = shift;
53              
54 9         269 my $value = join( '&', map uri_escape($_), $self->value );
55 9   66     444 my $no_httponly = defined( $self->http_only ) && $self->http_only == 0;
56              
57 9         432 my @headers = $self->name . '=' . $value;
58 9 50       278 push @headers, "Path=" . $self->path if $self->path;
59 9 100       411 push @headers, "Expires=" . $self->expires if $self->expires;
60 9 100       260 push @headers, "Domain=" . $self->domain if $self->domain;
61 9 100       223 push @headers, "SameSite=" . $self->same_site if $self->same_site;
62 9 100       219 push @headers, "Secure" if $self->secure;
63 9 100       69 push @headers, 'HttpOnly' unless $no_httponly;
64              
65 9         72 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             sub values {
90 4     4 1 13 my $self = shift;
91 4 50       9 return @{ $self->{'value'} || [] };
  4         35  
92             }
93              
94             # this is only for overloading; need a real sub to refer to, as the Moose
95             # attribute accessor won't be available at that point.
96 88     88   1943 sub _get_value { shift->value }
97              
98             has name => (
99             is => 'rw',
100             isa => Str,
101             required => 1,
102             );
103              
104             has expires => (
105             is => 'rw',
106             isa => Str,
107             required => 0,
108             coerce => sub {
109             Dancer2::Core::Time->new( expression => $_[0] )->gmt_string;
110             },
111             );
112              
113             has domain => (
114             is => 'rw',
115             isa => Str,
116             required => 0,
117             );
118              
119             has path => (
120             is => 'rw',
121             isa => Str,
122             default => sub {'/'},
123             predicate => 1,
124             );
125              
126             has secure => (
127             is => 'rw',
128             isa => Bool,
129             required => 0,
130             default => sub {0},
131             );
132              
133             has http_only => (
134             is => 'rw',
135             isa => Bool,
136             required => 0,
137             default => sub {1},
138             );
139              
140             has same_site => (
141             is => 'rw',
142             isa => Enum[qw[Strict Lax None]],
143             required => 0,
144             );
145              
146             1;
147              
148             __END__