Added recursive -r flag to prove example
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Engine / HTTP / Daemon.pm
index f8f87ed..00daf22 100644 (file)
@@ -3,7 +3,32 @@ package Catalyst::Engine::HTTP::Daemon;
 use strict;
 use base 'Catalyst::Engine::HTTP::Base';
 
+use Catalyst::Exception;
 use IO::Select;
+use IO::Socket;
+
+BEGIN {
+
+    if ( $^O eq 'MSWin32' ) {
+
+        *EINTR       = sub { 10004 };
+        *EINPROGRESS = sub { 10036 };
+        *EWOULDBLOCK = sub { 10035 };
+        *F_GETFL     = sub {     0 };
+        *F_SETFL     = sub {     0 };
+
+        *IO::Socket::blocking = sub {
+            my ( $self, $blocking ) = @_;
+            my $nonblocking = $blocking ? 0 : 1;
+            ioctl( $self, 0x8004667e, \$nonblocking );
+        };
+    }
+
+    else {
+        Errno->require;
+        Errno->import( qw[EWOULDBLOCK EINPROGRESS EINTR] );
+    }
+}
 
 =head1 NAME
 
@@ -64,14 +89,17 @@ sub run {
     $SIG{'PIPE'} = 'IGNORE';
 
     my $daemon = Catalyst::Engine::HTTP::Daemon::Catalyst->new(
-        Listen    => 1,
+        Listen    => SOMAXCONN,
         LocalPort => $port,
         ReuseAddr => 1,
         Timeout   => 5
     );
 
     unless ( defined $daemon ) {
-        die(qq/Failed to create daemon. Reason: '$!'/);
+
+        Catalyst::Exception->throw(
+            message => qq/Failed to create daemon. Reason: '$!'/
+        );
     }
 
     my $base = URI->new( $daemon->url )->canonical;
@@ -82,7 +110,7 @@ sub run {
 
     while (1) {
 
-        for my $client ( $select->can_read(1) ) {
+        for my $client ( $select->can_read(0.01) ) {
 
             if ( $client == $daemon ) {
                 $client = $daemon->accept;
@@ -97,7 +125,11 @@ sub run {
 
                 my $nread = $client->sysread( my $buf, 4096 );
 
-                unless ( defined($nread) && length($buf) ) {
+                unless ( $nread ) {
+
+                    next if $! == EWOULDBLOCK;
+                    next if $! == EINPROGRESS;
+                    next if $! == EINTR;
 
                     $select->remove($client);
                     $client->close;
@@ -135,12 +167,26 @@ sub run {
             $class->handler( $client->request, $client->response, $client );
         }
 
-        for my $client ( $select->can_write(1) ) {
+        for my $client ( $select->can_write(0.01) ) {
 
             next unless $client->response;
 
             unless ( $client->response_buffer ) {
-                $client->response_buffer = $client->response->as_string;
+
+                $client->response->header( Server => $daemon->product_tokens );
+
+                my $connection = $client->request->header('Connection') || '';
+
+                if ( $connection =~ /Keep-Alive/i ) {
+                    $client->response->header( 'Connection' => 'Keep-Alive' );
+                    $client->response->header( 'Keep-Alive' => 'timeout=60, max=100' );
+                }
+
+                if ( $connection =~ /close/i ) {
+                    $client->response->header( 'Connection' => 'close' );
+                }
+
+                $client->response_buffer = $client->response->as_string("\x0D\x0A");
                 $client->response_offset = 0;
             }
 
@@ -148,7 +194,11 @@ sub run {
                                             $client->response_length,
                                             $client->response_offset );
 
-            unless ( defined($nwrite) ) {
+            unless ( $nwrite ) {
+
+                next if $! == EWOULDBLOCK;
+                next if $! == EINPROGRESS;
+                next if $! == EINTR;
 
                 $select->remove($client);
                 $client->close;
@@ -160,9 +210,19 @@ sub run {
 
             if ( $client->response_offset == $client->response_length ) {
 
-                my $connection = $client->request->header('Connection');
+                my $connection = $client->request->header('Connection') || '';
+                my $protocol   = $client->request->protocol;
+                my $persistent = 0;
+
+                if ( $protocol eq 'HTTP/1.1' && $connection !~ /close/i ) {
+                    $persistent++;
+                }
+
+                if ( $protocol ne 'HTTP/1.1' && $connection =~ /Keep-Alive/i ) {
+                    $persistent++;
+                }
 
-                unless ( $connection && $connection =~ /Keep-Alive/i ) {
+                unless ( $persistent ) {
                     $select->remove($client);
                     $client->close;
                 }