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;