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 )