use Data::Dump qw(dump);
use Errno 'EWOULDBLOCK';
use HTTP::Date ();
+use HTTP::Headers;
use HTTP::Status;
use NEXT;
use Socket;
require Catalyst::Engine::HTTP::Restarter;
require Catalyst::Engine::HTTP::Restarter::Watcher;
-sub CHUNKSIZE () { 64 * 1024 }
-
-sub DEBUG () { $ENV{CATALYST_HTTP_DEBUG} || 0 }
+use constant CHUNKSIZE => 64 * 1024;
+use constant DEBUG => $ENV{CATALYST_HTTP_DEBUG} || 0;
=head1 NAME
my $status = $c->response->status;
my $message = status_message($status);
- print "$protocol $status $message\015\012";
+ my @headers;
+ push @headers, "$protocol $status $message";
$c->response->headers->header( Date => HTTP::Date::time2str(time) );
- $c->response->headers->header(
- Connection => $self->_keep_alive ? 'keep-alive' : 'close' );
-
$c->response->headers->header( Status => $status );
-
- # Avoid 'print() on closed filehandle Remote' warnings when using IE
- print $c->response->headers->as_string("\015\012") if *STDOUT->opened();
- print "\015\012" if *STDOUT->opened();
+
+ # Should we keep the connection open?
+ my $connection = $c->request->header('Connection');
+ if ( $self->{options}->{keepalive}
+ && $connection
+ && $connection =~ /^keep-alive$/i
+ ) {
+ $c->response->headers->header( Connection => 'keep-alive' );
+ $self->{_keepalive} = 1;
+ }
+ else {
+ $c->response->headers->header( Connection => 'close' );
+ }
+
+ push @headers, $c->response->headers->as_string("\x0D\x0A");
+
+ # Buffer the headers so they are sent with the first write() call
+ # This reduces the number of TCP packets we are sending
+ $self->{_header_buf} = join("\x0D\x0A", @headers, '');
}
=head2 $self->finalize_read($c)
# Ignore broken pipes as an HTTP server should
local $SIG{PIPE} = 'IGNORE';
+ # Restart on HUP
+ local $SIG{HUP} = sub {
+ $restart = 1;
+ warn "Restarting server on SIGHUP...\n";
+ };
+
LISTEN:
while ( !$restart ) {
while ( accept( Remote, $daemon ) ) {
unless ( uc($method) eq 'RESTART' ) {
# Fork
- if ( $options->{fork} ) { next if $pid = fork }
+ if ( $options->{fork} ) {
+ if ( $pid = fork ) {
+ DEBUG && warn "Forked child $pid\n";
+ next;
+ }
+ }
$self->_handler( $class, $port, $method, $uri, $protocol );
if ( my $error = delete $self->{_write_error} ) {
DEBUG && warn "Write error: $error\n";
close Remote;
- next LISTEN;
+
+ if ( !defined $pid ) {
+ next LISTEN;
+ }
}
- $daemon->close if defined $pid;
+ if ( defined $pid ) {
+ # Child process, close connection and exit
+ DEBUG && warn "Child process exiting\n";
+ $daemon->close;
+ exit;
+ }
}
else {
my $sockdata = $self->_socket_data( \*Remote );
last;
}
}
-
- exit if defined $pid;
}
continue {
close Remote;
REQUEST:
while (1) {
my ( $path, $query_string ) = split /\?/, $uri, 2;
-
+
# Initialize CGI environment
local %ENV = (
PATH_INFO => $path || '',