App-Foca
view release on metacpan or search on metacpan
lib/App/Foca/Server.pm view on Meta::CPAN
while (my $request = $connection->get_request) {
my $start = time;
log_request($connection->peerhost(), $request->uri->path);
my $response;
# Special commands?
if ($connection->peerhost() eq '127.0.0.1') {
if ($request->uri->path eq '/reload') {
$self->load_commands();
$response = $self->build_response(HTTP_OK,
"Commands reloaded");
} elsif ($request->uri->path eq '/status') {
$response = $self->prepare_status_response();
}
}
$response = $self->prepare_foca_response($connection, $request) unless
$response;
my $lat = (time-$start);
# Add latency
$response->header('X-Foca-ResponseTime', sprintf("%.5f", $lat));
$connection->send_response($response);
$connection->close;
}
exit 0;
}
}
exit 0;
}
=head2 B<prepare_status_response()>
Prepares a response (L<HTTP::Response>) for the /status request. /status
requests returns some stats about Foca server, such as: number of active
connections, number of closed/zombie connections (user connected and left
the connection open with a process that is no longer needed).
=cut
sub prepare_status_response {
my ($self) = @_;
my $table = Linux::Proc::Net::TCP->read;
my ($active_connections, $closed_connections) = (0, 0);
for my $entry (@$table) {
if ($entry->local_port == $self->{'port'}) {
if ($entry->st eq 'CLOSE_WAIT') {
$closed_connections++;
} elsif ($entry->st eq 'ESTABLISHED') {
$active_connections++;
}
}
}
my $body = "active_connections: $active_connections\n";
$body .= "closed_connections: $closed_connections\n";
return $self->build_response(HTTP_OK, $body);
}
=head2 B<prepare_foca_response($connection, $request)>
Prepares a response (L<HTTP::Response>) for a given foca request (L<HTTP::Request>).
=cut
sub prepare_foca_response {
my ($self, $connection, $request) = @_;
my $headers = $request->headers;
my $method = $request->method;
# Ok, we getting GET or HEAD? the only ones we allow
if (grep($method eq uc $_, qw(GET HEAD))) {
# We got params?
my $params = $headers->header('Foca-Cmd-Params') || '';
# *sanitize* the parameters
$params = $self->_sanitize_parameters($params);
# Ok, which command?
my $command = $request->uri->path || '';
if ($command =~ m#^/foca/(\S+)(\/)?#) {
$command = $1;
}
# We got command?
unless ($command) {
return $self->build_response(HTTP_NOT_ACCEPTABLE,
"Missing command");
}
# Cool, now load the commands from memory
my $commands = $self->{'cache'}->get('foca_commands');
$commands = {} unless $commands;
unless ($commands) {
log_error("There are no commands available");
return $self->build_response(HTTP_NOT_IMPLEMENTED, "No commands available");
}
# Ok, the command is valid?
unless ($commands->{$command}) {
return $self->build_response(HTTP_NOT_FOUND, "Unknown command");
}
# Validate request
my ($is_valid, $msg) = $self->validate_request($command, $request);
unless ($is_valid) {
if ($msg) {
return $self->build_response(HTTP_FORBIDDEN, $msg);
} else {
return $self->build_response(HTTP_FORBIDDEN);
}
}
my ($code, $output) = $self->run_cmd(
$connection,
$command,
$commands->{$command},
$params);
# Ok, we got a command, now lets
if ($code == FOCA_RUN_RC_OK) {
return $self->build_response(HTTP_OK, $output);
} elsif ($code == FOCA_RUN_RC_TIMEOUT_CMD) {
return $self->build_response(HTTP_REQUEST_TIMEOUT, 'Timed out');
} else {
return $self->build_response(HTTP_INTERNAL_SERVER_ERROR, $output);
}
}
}
( run in 0.464 second using v1.01-cache-2.11-cpan-acf6aa7dc9e )