Container-Builder
view release on metacpan or search on metacpan
examples/fatpacked.plackup view on Meta::CPAN
use Plack::Middleware::ContentLength;
use POSIX qw(EINTR);
use Socket qw(IPPROTO_TCP);
use Try::Tiny;
use Time::HiRes qw(time);
use constant TCP_NODELAY => try { Socket::TCP_NODELAY };
my $alarm_interval;
BEGIN {
if ($^O eq 'MSWin32') {
$alarm_interval = 1;
} else {
Time::HiRes->import('alarm');
$alarm_interval = 0.1;
}
}
use constant MAX_REQUEST_SIZE => 131072;
use constant MSWin32 => $^O eq 'MSWin32';
sub new {
my($class, %args) = @_;
my $self = bless {
($args{listen_sock} ? (
listen_sock => $args{listen_sock},
host => $args{listen_sock}->sockhost,
port => $args{listen_sock}->sockport,
):(
host => $args{host} || 0,
port => $args{port} || 8080,
)),
timeout => $args{timeout} || 300,
server_software => $args{server_software} || $class,
server_ready => $args{server_ready} || sub {},
ssl => $args{ssl},
ipv6 => $args{ipv6},
ssl_key_file => $args{ssl_key_file},
ssl_cert_file => $args{ssl_cert_file},
}, $class;
$self;
}
sub run {
my($self, $app) = @_;
$self->setup_listener();
$self->accept_loop($app);
}
sub prepare_socket_class {
my($self, $args) = @_;
if ($self->{ssl} && $self->{ipv6}) {
Carp::croak("SSL and IPv6 are not supported at the same time (yet). Choose one.");
}
if ($self->{ssl}) {
eval { require IO::Socket::SSL; 1 }
or Carp::croak("SSL suport requires IO::Socket::SSL");
$args->{SSL_key_file} = $self->{ssl_key_file};
$args->{SSL_cert_file} = $self->{ssl_cert_file};
return "IO::Socket::SSL";
} elsif ($self->{ipv6}) {
eval { require IO::Socket::IP; 1 }
or Carp::croak("IPv6 support requires IO::Socket::IP");
$self->{host} ||= '::';
$args->{LocalAddr} ||= '::';
return "IO::Socket::IP";
}
return "IO::Socket::INET";
}
sub setup_listener {
my $self = shift;
$self->{listen_sock} ||= do {
my %args = (
Listen => SOMAXCONN,
LocalPort => $self->{port},
LocalAddr => $self->{host},
Proto => 'tcp',
ReuseAddr => 1,
);
my $class = $self->prepare_socket_class(\%args);
$class->new(%args)
or die "failed to listen to port $self->{port}: $!";
};
$self->{server_ready}->({ %$self, proto => $self->{ssl} ? 'https' : 'http' });
}
sub accept_loop {
my($self, $app) = @_;
$app = Plack::Middleware::ContentLength->wrap($app);
while (1) {
local $SIG{PIPE} = 'IGNORE';
if (my $conn = $self->{listen_sock}->accept) {
if (defined TCP_NODELAY) {
$conn->setsockopt(IPPROTO_TCP, TCP_NODELAY, 1)
or die "setsockopt(TCP_NODELAY) failed:$!";
}
my $env = {
SERVER_PORT => $self->{port},
SERVER_NAME => $self->{host},
SCRIPT_NAME => '',
REMOTE_ADDR => $conn->peerhost,
REMOTE_PORT => $conn->peerport || 0,
'psgi.version' => [ 1, 1 ],
'psgi.errors' => *STDERR,
'psgi.url_scheme' => $self->{ssl} ? 'https' : 'http',
'psgi.run_once' => Plack::Util::FALSE,
'psgi.multithread' => Plack::Util::FALSE,
'psgi.multiprocess' => Plack::Util::FALSE,
'psgi.streaming' => Plack::Util::TRUE,
'psgi.nonblocking' => Plack::Util::FALSE,
'psgix.harakiri' => Plack::Util::TRUE,
'psgix.input.buffered' => Plack::Util::TRUE,
'psgix.io' => $conn,
( run in 1.397 second using v1.01-cache-2.11-cpan-6aa56a78535 )