Any-Daemon-HTTP
view release on metacpan or search on metacpan
lib/Any/Daemon/FCGI/ClientConn.pm view on Meta::CPAN
}
elsif($type eq 'PARAMS')
{ if(length $$body) { $reqdata->{params} .= $$body }
else { $reqdata->{params_complete} = 1 }
}
elsif($type eq 'STDIN') # Not for Authorizer
{ if(length $$body) { $reqdata->{stdin} .= $$body }
else { $reqdata->{stdin_complete} = 1 }
}
elsif($type eq 'DATA') # Filter only
{ if(length $$body) { $reqdata->{data} .= $$body }
else { $reqdata->{data_complete} = 1 }
}
last if $reqdata->{params_complete}
&& $reqdata->{stdin_complete}
&& $reqdata->{data_complete};
}
# We still have this record in $reqdata
my $req_id = $reqdata->{request_id};
delete $requests->{$req_id};
my $enc_params = delete $reqdata->{params};
my $p = $reqdata->{params} = eval { $self->_body2hash(\$enc_params) };
if($@)
{ notice __x"fcgi {id} params error: {err}", id => $req_id, err => $@;
delete $requests->{$req_id};
return $self->get_request;
}
my $expected_stdin = $p->{CONTENT_LENGTH} || 0;
$expected_stdin == length $reqdata->{stdin}
or error __x"fcgi {id} received {got} bytes on stdin, expected {need}"
, id => $req_id
, got => length $reqdata->{stdin}
, need => $expected_stdin;
my $expected_data = $p->{FCGI_DATA_LENGTH} || 0;
$expected_data == length $reqdata->{data}
or error __x"fcgi {id} received {got} bytes for data, expected {need}"
, id => $req_id
, got => length $reqdata->{data}
, need => $expected_data;
my $request = Any::Daemon::FCGI::Request->new($reqdata);
my $remote_ip = $request->param('REMOTE_ADDR');
my $remote_host = gethostbyaddr inet_aton($remote_ip), AF_INET;
info __x"fcgi {id} request from {host}"
, id => $req_id
, host => $remote_host || $remote_ip;
$self->keep_connection
or $self->socket->shutdown(SHUT_RD);
$request;
}
sub send_response($;$)
{ my ($self, $response, $stderr) = @_;
#XXX Net::Async::FastCGI::Request demonstrates how to catch stdout and
#XXX stderr via ties. We don't use that here: cleanly work with
#XXX HTTP::Message objects... errors are logged locally.
my $req_id = $response->request->request_id;
# Simply "Status: " in front of the Response header will make the whole
# message HTTP::Response into a valid CGI response.
$self->_reply_record(STDOUT => $req_id
, 'Status: '.$response->as_string(CRLF));
$self->_reply_record(STDOUT => $req_id, '');
if($stderr && length $$stderr)
{ $self->_reply_record(STDERR => $req_id, $$stderr);
$self->_reply_record(STDERR => $req_id, '');
}
$self->_fcgi_end_request(REQUEST_COMPLETE => $req_id);
$self->keep_connection
or $self->socket->shutdown(SHUT_WR);
$self;
}
sub keep_connection()
{ my $self = shift;
$self->{ADFC_keep_conn} || keys %{$self->{ADFC_requests}}
}
#### MANAGEMENT RECORDS
# have req_id==0
sub _management_record($$)
{ my ($self, $type, $body) = @_;
$type eq 'GET_VALUES' ? $self->_fcgi_get_values($body)
: $self->_fcgi_unknown($body);
}
# Request record FCGI_GET_VALUES may be used by the front-end server to
# collect back_end settings. In Apache, you have to configure it manually.
sub _fcgi_get_values($)
{ my $self = shift;
my %need = $self->_body2hash(shift);
# The maximum number of concurrent transport connections this
# application will accept.
$need{FCGI_MAX_CONNS} = $self->{ADFC_max_conns}
if exists $need{FCGI_MAX_CONNS};
# The maximum number of concurrent requests this application will accept.
$need{FCGI_MAX_REQS} = $self->{ADFC_max_reqs}
if exists $need{FCGI_MAX_REQS};
# "0" if this application does not multiplex connections (i.e. handle
# concurrent requests over each connection), "1" otherwise.
$need{FCGI_MPXS_CONNS} = 0
if exists $need{FCGI_MPXS_CONNS};
$self->_reply_record(GET_VALUES_RESULT => 0, $self->hash2body(\%need));
}
# Reply record FCGI_UNKNOWN_TYPE is designed for protocol upgrades: to
# respond to unknown record types.
sub _fcgi_unknown($)
{ my ($self, $body) = @_;
$self->_reply_record(UNKNOWN_TYPE => 0, '');
}
# Reply END_REQUEST is used for all ways to close a BEGIN_REQUEST session.
# It depends on the $status code which additionals fields were sent.
( run in 0.501 second using v1.01-cache-2.11-cpan-39bf76dae61 )