You are viewing a plain text version of this content. The canonical link for it is here.
Posted to axkit-dev@xml.apache.org by ma...@sergeant.org on 2006/08/01 05:12:41 UTC

[SVN] [24] Support connection notes fields

Revision: 24
Author:   matt
Date:     2006-08-01 03:12:17 +0000 (Tue, 01 Aug 2006)

Log Message:
-----------
Support connection notes fields
Support POST/PUT data via body_data callbacks
Support potential for persistent (keep-alive) connections

Modified Paths:
--------------
    trunk/lib/AxKit2/Client.pm
    trunk/lib/AxKit2/Connection.pm
    trunk/lib/AxKit2/Plugin.pm

Modified: trunk/lib/AxKit2/Client.pm
===================================================================
--- trunk/lib/AxKit2/Client.pm	2006-07-31 21:24:27 UTC (rev 23)
+++ trunk/lib/AxKit2/Client.pm	2006-08-01 03:12:17 UTC (rev 24)
@@ -143,4 +143,19 @@
     }
 }
 
+sub hook_body_data {
+    my $self = shift;
+    my ($ret, $out) = $self->run_hooks('body_data', @_);
+    if ($ret == DECLINED) {
+        $self->process_request();
+        return;
+    }
+    elsif ($ret == OK) {
+        return 1;
+    }
+    else {
+        # TODO: output error stuff?
+    }
+}
+
 1;
\ No newline at end of file

Modified: trunk/lib/AxKit2/Connection.pm
===================================================================
--- trunk/lib/AxKit2/Connection.pm	2006-07-31 21:24:27 UTC (rev 23)
+++ trunk/lib/AxKit2/Connection.pm	2006-08-01 03:12:17 UTC (rev 24)
@@ -18,6 +18,7 @@
     ditch_leading_rn
     server_config
     http_headers_sent
+    notes
     );
 
 use constant CLEANUP_TIME => 5; # every N seconds
@@ -41,6 +42,7 @@
     $self->{headers_string} = '';
     $self->{ditch_leading_rn} = 0; # TODO - work out how to set that...
     $self->{server_config} = $servconf;
+    $self->{notes} = {};
     
     $self->log(LOGINFO, "Connection from " . $self->peer_addr_string);
     # allow connect hook to disconnect us
@@ -57,6 +59,13 @@
     return $self->{server_config};
 }
 
+sub notes {
+    my AxKit2::Connection $self = shift;
+    my $key  = shift;
+    @_ and $self->{notes}->{$key} = shift;
+    $self->{notes}->{$key};
+}
+
 sub max_idle_time       { 30 }
 sub max_connect_time    { 180 }
 sub event_err { my AxKit2::Connection $self = shift; $self->close("Error") }
@@ -64,6 +73,14 @@
 
 sub event_read {
     my AxKit2::Connection $self = shift;
+    $self->{alive_time} = time;
+    
+    if ($self->{headers_in}) {
+        # already got the headers... do we get a body too?
+        my $bref = $self->read(8192);
+        return $self->close($!) unless defined $bref;
+        return $self->hook_body_data($bref);
+    }
     my $to_read = MAX_HTTP_HEADER_LENGTH - length($self->{headers_string});
     my $bref = $self->read($to_read);
     return $self->close($!) unless defined $bref;
@@ -108,7 +125,7 @@
     
     $self->{ditch_leading_rn} = 0;
     
-    $self->process_request();
+    $self->process_request() if $self->{headers_in}->request_method =~ /GET|HEAD/;
 }
 
 sub headers_out {
@@ -151,9 +168,58 @@
     $self->hook_xmlresponse(AxKit2::Processor->new($hd->filename))
       || $self->hook_response($hd);
     
-    $self->close();
+    $self->http_response_sent();
 }
 
+# called when we've finished writing everything to a client and we need
+# to reset our state for another request.  returns 1 to mean that we should
+# support persistence, 0 means we're discarding this connection.
+sub http_response_sent {
+    my AxKit2::Connection $self = $_[0];
+
+    # close if we're supposed to
+    if (
+        ! defined $self->{headers_out} ||
+        ! $self->{headers_out}->res_keep_alive($self->{headers_in})
+        )
+    {
+        # do a final read so we don't have unread_data_waiting and RST
+        # the connection.  IE and others send an extra \r\n after POSTs
+        my $dummy = $self->read(5);
+
+        # close if we have no response headers or they say to close
+        $self->close("no_keep_alive");
+        return 0;
+    }
+
+    # if they just did a POST, set the flag that says we might expect
+    # an unadvertised \r\n coming from some browsers.  Old Netscape
+    # 4.x did this on all POSTs, and Firefox/Safari do it on
+    # XmlHttpRequest POSTs.
+    if ($self->{headers_in}->request_method eq "POST") {
+        $self->{ditch_leading_rn} = 1;
+    }
+
+    # now since we're doing persistence, uncork so the last packet goes.
+    # we will recork when we're processing a new request.
+    # TODO: Disabled because this seemed mostly relevant to Perlbal...
+    #$self->tcp_cork(0);
+
+    # reset state
+    $self->{alive_time}            = $self->{create_time} = time;
+    $self->{headers_string}        = '';
+    $self->{headers_in}            = undef;
+    $self->{headers_out}           = undef;
+    $self->{http_headers_sent}     = 0;
+    
+    # NOTE: because we only speak 1.0 to clients they can't have
+    # pipeline in a read that we haven't read yet.
+    $self->watch_read(1);
+    $self->watch_write(0);
+    return 1;
+}
+
+
 # Cleanup routine to get rid of timed out sockets
 sub _do_cleanup {
     my $now = time;

Modified: trunk/lib/AxKit2/Plugin.pm
===================================================================
--- trunk/lib/AxKit2/Plugin.pm	2006-07-31 21:24:27 UTC (rev 23)
+++ trunk/lib/AxKit2/Plugin.pm	2006-08-01 03:12:17 UTC (rev 24)
@@ -9,7 +9,7 @@
 # more or less in the order they will fire
 our @hooks = qw(
     logging config pre-connection connect post_read_request
-    uri_translation access_control authentication authorization
+    body_data uri_translation access_control authentication authorization
     fixup xmlresponse response disconnect error
 );
 our %hooks = map { $_ => 1 } @hooks;