r9710@zaphod (orig r6123): andyg | 2007-02-28 17:45:31 +1100
Kieren Diment [Mon, 12 Mar 2007 11:06:43 +0000 (11:06 +0000)]
Improved performance and stability of built-in HTTP server.  Ripped out keep-alive hack.  Increased chunk size from 4K to 64K.
r9711@zaphod (orig r6124):  jrockway | 2007-03-01 06:30:17 +1100
r26049@foo:  jon | 2007-02-28 12:50:05 -0600
mention that catalyst developers need catalyst::devel; bump catalyst version to 5.7
patch from jshirley.

r9712@zaphod (orig r6125):  andyg | 2007-03-01 09:43:40 +1100
Remove the time prefix from warn calls, was using it for debugging
r9713@zaphod (orig r6126):  fireartist | 2007-03-02 03:55:18 +1100
disabled HTMLEscape filter test - broken by HTML::Element.
HTML::Element unicode escaping fixed though, so enabled test, and require
v3.22.
documented request for maintainers.
bumped version number to 1.11 for cpan release

r9714@zaphod (orig r6127):  jshirley | 2007-03-02 10:29:58 +1100
Creating branch for new site development

r9715@zaphod (orig r6128):  andyg | 2007-03-02 17:45:16 +1100
Creating a dir for new PoCo::Catalyst wrapper around the POE engine
r9716@zaphod (orig r6129):  dec | 2007-03-02 18:11:38 +1100
Initial, basic, POE::Component::Catalyst with little to no testing.
r9717@zaphod (orig r6130):  adam | 2007-03-03 04:23:59 +1100
Added some debug logging - From Dave Rolksy

r9718@zaphod (orig r6131):  andyg | 2007-03-03 04:32:29 +1100
HTTP::POE: Support for setting custom alias name.  status() method
r9719@zaphod (orig r6132):  andyg | 2007-03-03 04:33:26 +1100
PoCo::Catalyst: Added a basic test suite, cleaned up the spawn options a bit
r9720@zaphod (orig r6133):  adam | 2007-03-03 06:51:56 +1100
Adding Catalyst::Log::Log4perl branch directory

r9721@zaphod (orig r6134):  adam | 2007-03-03 06:52:38 +1100
Branching for Sebastian Willert's fixes for cspec issues. (Allows for the proper line and file name)

r9722@zaphod (orig r6135):  adam | 2007-03-03 06:56:31 +1100
Sebastian Willert's fixes for broken cspec's.  Allows for proper reporting
of file line numbers.

r9723@zaphod (orig r6136):  marcus | 2007-03-04 10:46:58 +1100
wrong variable dec
r9724@zaphod (orig r6137):  andyg | 2007-03-07 03:27:13 +1100
RequireSSL 0.06, no_cache option, work properly under restarter and POE servers
r9725@zaphod (orig r6138):  nothingmuch | 2007-03-07 09:15:56 +1100
version bump
r9726@zaphod (orig r6139):  castaway | 2007-03-07 09:32:05 +1100
Added Catalyst-Model-S3 for davecardwell

r9727@zaphod (orig r6140):  davecardwell | 2007-03-07 14:02:28 +1100
Catalyst::Model::S3 - Catalyst Model for Amazon's S3 web service
importing v0.01

r9728@zaphod (orig r6141):  nothingmuch | 2007-03-07 14:41:48 +1100
fix tests
r9729@zaphod (orig r6142):  nothingmuch | 2007-03-07 14:43:36 +1100
blah
r9730@zaphod (orig r6143):  nothingmuch | 2007-03-07 14:44:21 +1100
- tagged Catalyst-View-TT-FunctionGenerator-0.02

Changes
lib/Catalyst/Engine/HTTP.pm

diff --git a/Changes b/Changes
index 12a52d9..b4e09ea 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,6 +1,8 @@
 This file documents the revision history for Perl extension Catalyst.
 
 5.7007  ??
+        - Performance and stability improvements to the built-in HTTP server.
+        - Built-in server no longer supports -k (keep-alive).
         - Don't ignore file uploads if form contains a text field with the same name.
           (Carl Franks)
         - Support restart_delay of 0 (for use in the POE engine).
index e1682af..8eb4dc3 100644 (file)
@@ -5,6 +5,7 @@ use base 'Catalyst::Engine::CGI';
 use Data::Dump qw(dump);
 use Errno 'EWOULDBLOCK';
 use HTTP::Date ();
+use HTTP::Headers;
 use HTTP::Status;
 use NEXT;
 use Socket;
@@ -53,17 +54,18 @@ sub finalize_headers {
     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( Connection => '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();
+    
+    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)
@@ -240,12 +242,20 @@ sub run {
 
             Remote->blocking(1);
         
-            # Read until we see all headers
+            # Read until we see a newline
             $self->{inputbuf} = '';
+        
+            while (1) {
+                my $read = sysread Remote, my $buf, CHUNKSIZE;
+            
+                if ( !$read ) {
+                    DEBUG && warn "EOF or error: $!\n";
+                    next LISTEN;
+                }
             
-            if ( !$self->_read_headers ) {
-                # Error reading, give up
-                next LISTEN;
+                DEBUG && warn "Read $read bytes\n";
+                $self->{inputbuf} .= $buf;
+                last if $self->{inputbuf} =~ /(\x0D\x0A?|\x0A\x0D?)/s;
             }
 
             my ( $method, $uri, $protocol ) = $self->_parse_request_line;
@@ -327,82 +337,36 @@ sub _handler {
     $sel->add( \*STDIN );
     
     REQUEST:
-    while (1) {
-        my ( $path, $query_string ) = split /\?/, $uri, 2;
-
-        # Initialize CGI environment
-        local %ENV = (
-            PATH_INFO       => $path         || '',
-            QUERY_STRING    => $query_string || '',
-            REMOTE_ADDR     => $sockdata->{peeraddr},
-            REMOTE_HOST     => $sockdata->{peername},
-            REQUEST_METHOD  => $method || '',
-            SERVER_NAME     => $sockdata->{localname},
-            SERVER_PORT     => $port,
-            SERVER_PROTOCOL => "HTTP/$protocol",
-            %copy_of_env,
-        );
-
-        # Parse headers
-        if ( $protocol >= 1 ) {
-            $self->_parse_headers;
-        }
-
-        # Pass flow control to Catalyst
-        $class->handle_request;
-    
-        DEBUG && warn "Request done\n";
-    
-        # Allow keepalive requests, this is a hack but we'll support it until
-        # the next major release.
-        if ( delete $self->{_keepalive} ) {
-            
-            DEBUG && warn "Reusing previous connection for keep-alive request\n";
-            
-            if ( $sel->can_read(1) ) {            
-                if ( !$self->_read_headers ) {
-                    # Error reading, give up
-                    last REQUEST;
-                }
+    my ( $path, $query_string ) = split /\?/, $uri, 2;
+
+    # Initialize CGI environment
+    local %ENV = (
+        PATH_INFO       => $path         || '',
+        QUERY_STRING    => $query_string || '',
+        REMOTE_ADDR     => $sockdata->{peeraddr},
+        REMOTE_HOST     => $sockdata->{peername},
+        REQUEST_METHOD  => $method || '',
+        SERVER_NAME     => $sockdata->{localname},
+        SERVER_PORT     => $port,
+        SERVER_PROTOCOL => "HTTP/$protocol",
+        %copy_of_env,
+    );
 
-                ( $method, $uri, $protocol ) = $self->_parse_request_line;
-                
-                DEBUG && warn "Parsed request: $method $uri $protocol\n";
-                
-                # Force HTTP/1.0
-                $protocol = '1.0';
-                
-                next REQUEST;
-            }
-            
-            DEBUG && warn "No keep-alive request within 1 second\n";
-        }
-        
-        last REQUEST;
+    # Parse headers
+    if ( $protocol >= 1 ) {
+        $self->_parse_headers;
     }
-    
-    DEBUG && warn "Closing connection\n";
-
-    close Remote;
-}
 
-sub _read_headers {
-    my $self = shift;
-    
-    while (1) {
-        my $read = sysread Remote, my $buf, CHUNKSIZE;
-    
-        if ( !$read ) {
-            DEBUG && warn "EOF or error: $!\n";
-            return;
-        }
+    # Pass flow control to Catalyst
+    $class->handle_request;
     
-        DEBUG && warn "Read $read bytes\n";
-        $self->{inputbuf} .= $buf;
-        last if $self->{inputbuf} =~ /(\x0D\x0A?\x0D\x0A?|\x0A\x0D?\x0A\x0D?)/s;
-    }
+    DEBUG && warn "Request done\n";
     
-    return 1;
+    # XXX: We used to have a hack for keep-alive here but keep-alive
+    # has no place in a single-tasking server like this.  Use HTTP::POE
+    # if you want keep-alive.
+
+    close Remote;
 }
 
 sub _parse_request_line {