#!/usr/bin/perl
use strict;
use warnings;
use HTTP::Engine;
my $engine = HTTP::Engine->new(
interface => {
module => 'ServerSimple',
args => {
host => 'localhost',
port => '8080',
},
request_handler => \&handle_request,
},
);
use HTTP::Engine::Response;
sub fisher_yates_shuffle {
my $deck = shift; # $deck is a reference to an array
return unless @$deck; # must not be empty!
my $i = @$deck;
while ( --$i ) {
my $j = int rand( $i + 1 );
@$deck[ $i, $j ] = @$deck[ $j, $i ];
}
}
sub randcookie {
my (@chars) = map { chr($_) } map { ord('A') .. ord('z') } 1 .. 10;
fisher_yates_shuffle( \@chars );
return join '', @chars[ 0 .. 10 ];
}
sub handle_request {
my $req = shift;
my $resp = HTTP::Engine::Response->new();
use YAML::XS qw( Dump );
my $ctext = Dump({
cookies => $req->cookies ,
headers => $req->headers,
request_uri => $req->request_uri,
} );
$resp->status(200);
$resp->headers->header( 'Content-Type' => 'text/plain' );
$resp->body( $ctext );
if( $req->request_uri =~ qr{/normal$} ){
normal_cookies( $resp );
return $resp;
}
if( $req->request_uri =~ qr{/normal2$} ){
normal_cookies2( $resp );
return $resp;
}
if( $req->request_uri =~ qr{/weird$} ){
weird_cookies( $resp );
return $resp;
}
if( $req->request_uri =~ qr{/weird2$} ){
weird_cookies2( $resp );
return $resp;
}
if( $req->request_uri =~ qr{/weird3$} ){
weird_cookies3( $resp );
return $resp;
}
if( $req->request_uri =~ qr{/weird4$} ){
weird_cookies4( $resp );
return $resp;
}
$resp->headers->header( 'Content-Type' => "text/html" );
$resp->body(<<'EOF');
<ul>
<li><a href="/weird">Weird Cookies ( 2 cookies, 1 path, 1 string ) </a>
<li><a href="/weird2">Weird Cookies2 ( 2 cookies, 1 path, array ) </a>
<li><a href="/weird3">Weird Cookies3 ( 2 cookies, 2 paths, 1 string ) </a>
<li><a href="/weird4">Weird Cookies4 ( 2 cookies, 2 paths, array ) </a>
<li><a href="/normal">Normal Cookies ( 1 value, 1 path ) </a>
<li><a href="/normal2">Normal Cookies2 ( 1 path, valuearray )( WARNING: Kills Server )</a>
</ul>
EOF
return $resp;
}
# Firefox only returns the most recently set value of foo.
sub normal_cookies {
my $resp = shift;
$resp->cookies->{foo} = { value => randcookie() };
}
# Firefox only returns the most recently set value of foo.
sub normal_cookies2 {
my $resp = shift;
# this is illegal.
$resp->cookies->{foo} = [
{ value => 'A' . randcookie() },
{ value => 'B' . randcookie() },
];
}
#
#
# Note: We sent 2 cookies with identical keys,
# but firefox only sees the first, and returns only the first.
#
sub weird_cookies {
my $resp = shift;
$resp->headers->header('Set-Cookie' => 'foo=A' . randcookie(). '; path=/; foo=B' . randcookie() . '; path=/;' );
}
#
# This also sends 2 cookies, but puts a \n in the response, ie:
# >>
# Connection: close
# Content-Length: 586
# Content-Type: text/plain
# Set-Cookie: foo=AqZI_GmTOBlV; path=/;
# foo=BwMD^frWvQoW; path=/;
# Status: 200
# >>
# Firefox in this case only sees the last cookie.
#
sub weird_cookies2 {
my $resp = shift;
$resp->headers->header('Set-Cookie' => [
'foo=A' . randcookie(). '; path=/;',
'foo=B' . randcookie() . '; path=/;'
]);
}
sub weird_cookies3 {
my $resp = shift;
$resp->headers->header('Set-Cookie' => 'foo=A' . randcookie(). '; path=/; foo=B' . randcookie() . '; path=/wierd3;' );
}
sub weird_cookies4 {
my $resp = shift;
$resp->headers->header('Set-Cookie' => [
'foo=A' . randcookie(). '; path=/;',
'foo=B' . randcookie() . '; path=/weird4;'
]);
}
$engine->run();