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 )