Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions lib/Dancer/Cookie.pm
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ package Dancer::Cookie;
use strict;
use warnings;

use Carp;
use URI::Escape;

use base 'Dancer::Object';
__PACKAGE__->attributes( qw/name expires domain path secure http_only/ );
__PACKAGE__->attributes( qw/name expires domain path same_site secure http_only/ );

sub init {
my ($self, %args) = @_;
Expand All @@ -22,6 +23,16 @@ sub init {
$self->expires($time);
}
$self->path('/') unless defined $self->path;

# If we have a same_site attribute, ensure it's sane:
if (my $same_site = $self->same_site) {
if ($same_site !~ m{^(Strict|Lax|None)$}) {
Carp::croak(
"Invalid same_site value '$same_site'"
. " - must be 'Strict', 'Lax' or 'None', see RFC6265bis"
);
}
}
}

sub to_header {
Expand All @@ -35,10 +46,11 @@ sub to_header {
$name =~ s/[=,; \t\r\n\013\014]//mg;

my @headers = $name . '=' . $value;
push @headers, "path=" . $self->path if $self->path;
push @headers, "expires=" . $self->expires if $self->expires;
push @headers, "domain=" . $self->domain if $self->domain;
push @headers, "Secure" if $self->secure;
push @headers, "path=" . $self->path if $self->path;
push @headers, "expires=" . $self->expires if $self->expires;
push @headers, "domain=" . $self->domain if $self->domain;
push @headers, "Secure" if $self->secure;
push @headers, "SameSite=" . $self->same_site if $self->same_site;
push @headers, 'HttpOnly' unless $no_httponly;

return join '; ', @headers;
Expand Down
2 changes: 2 additions & 0 deletions lib/Dancer/Session/Abstract.pm
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ sub write_session_id {
secure => setting('session_secure'),
http_only => defined(setting("session_is_http_only")) ?
setting("session_is_http_only") : 1,
same_site => defined(setting("session_same_site")) ?
setting("session_same_site") ? 'None',
);
if (my $expires = setting('session_expires')) {
# It's # of seconds from the current time
Expand Down
10 changes: 7 additions & 3 deletions t/09_cookies/05_api.t
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ use Dancer ':syntax';

my @tests = (
{ name => 'foo', value => 42 , opts => {}},
{ name => 'foo', value => 42 , opts => { http_only => 1 } },
{ name => 'msg', value => 'hello; world', opts => {} },
{ name => 'msg', value => 'hello; world', opts => { http_only => 0 } },
{ name => 'foo', value => 42 , opts => { http_only => 1 } },
{ name => 'msg', value => 'hello; world', opts => {} },
{ name => 'msg', value => 'hello; world', opts => { http_only => 0 } },
{ name => 'ss', value => 'samesitetest', opts => { same_site => 'Lax' } },
);

plan tests => scalar (@tests * 5) + 12;
Expand All @@ -21,6 +22,9 @@ foreach my $test (@tests) {
is $c->http_only,
(exists($test->{opts}{http_only}) ? $test->{opts}{http_only} : undef),
"HttpOnly is correctly set";
is $c->same_site,
(exists($test->{opts}{same_site}) ? $test->{opts}{same_site} : undef),
"SameSite is correctly set";
}

{
Expand Down