Files
zonemaster.es/zonemaster-backend/script/zonemaster_backend_rpcapi.psgi

253 lines
5.9 KiB
Plaintext
Raw Permalink Normal View History

#!/usr/bin/env perl
use strict;
use warnings;
our $VERSION = '1.1.0';
use 5.14.2;
use English qw( $PID );
use JSON::PP;
use JSON::RPC::Dispatch;
use Log::Any qw( $log );
use Log::Any::Adapter;
use POSIX;
use Plack::Builder;
use Plack::Response;
use Router::Simple::Declare;
use Try::Tiny;
BEGIN {
$ENV{PERL_JSON_BACKEND} = 'JSON::PP';
undef $ENV{LANGUAGE};
};
use Zonemaster::Backend::RPCAPI;
use Zonemaster::Backend::Config;
use Zonemaster::Backend::Metrics;
local $| = 1;
Log::Any::Adapter->set(
'+Zonemaster::Backend::Log',
log_level => $ENV{ZM_BACKEND_RPCAPI_LOGLEVEL},
json => $ENV{ZM_BACKEND_RPCAPI_LOGJSON},
stderr => 1
);
$SIG{__WARN__} = sub {
$log->warning(map s/^\s+|\s+$//gr, map s/\n/ /gr, @_);
};
my $config = Zonemaster::Backend::Config->load_config();
Zonemaster::Backend::Metrics->setup($config->METRICS_statsd_host, $config->METRICS_statsd_port);
Zonemaster::Engine::init_engine();
builder {
enable sub {
my $app = shift;
# Make sure we can connect to the database
$config->new_DB();
return $app;
};
};
my $handler = Zonemaster::Backend::RPCAPI->new( { config => $config } );
my $router = router {
############## FRONTEND ####################
connect "version_info" => {
handler => $handler,
action => "version_info"
};
# Experimental
connect "system_versions" => {
handler => $handler,
action => "system_versions"
};
connect "profile_names" => {
handler => $handler,
action => "profile_names"
};
# Experimental
connect "conf_profiles" => {
handler => $handler,
action => "conf_profiles"
};
connect "get_language_tags" => {
handler => $handler,
action => "get_language_tags"
};
# Experimental
connect "conf_languages" => {
handler => $handler,
action => "conf_languages"
};
connect "get_host_by_name" => {
handler => $handler,
action => "get_host_by_name"
};
# Experimental
connect "lookup_address_records" => {
handler => $handler,
action => "lookup_address_records"
};
connect "get_data_from_parent_zone" => {
handler => $handler,
action => "get_data_from_parent_zone"
};
# Experimental
connect "lookup_delegation_data" => {
handler => $handler,
action => "lookup_delegation_data"
};
connect "start_domain_test" => {
handler => $handler,
action => "start_domain_test"
};
# Experimental
connect "job_create" => {
handler => $handler,
action => "job_create"
};
connect "test_progress" => {
handler => $handler,
action => "test_progress"
};
# Experimental
connect "job_status" => {
handler => $handler,
action => "job_status"
};
connect "get_test_params" => {
handler => $handler,
action => "get_test_params"
};
# Experimental
connect "job_params" => {
handler => $handler,
action => "job_params"
};
connect "get_test_results" => {
handler => $handler,
action => "get_test_results"
};
# Experimental
connect "job_results" => {
handler => $handler,
action => "job_results"
};
connect "get_test_history" => {
handler => $handler,
action => "get_test_history"
};
# Experimental
connect "domain_history" => {
handler => $handler,
action => "domain_history"
};
connect "batch_status" => {
handler => $handler,
action => "batch_status"
};
};
if ( $config->RPCAPI_enable_user_create or $config->RPCAPI_enable_add_api_user ) {
$log->info('Enabling add_api_user method');
$router->connect("add_api_user", {
handler => $handler,
action => "add_api_user"
});
$router->connect("user_create", {
handler => $handler,
action => "user_create"
});
}
if ( $config->RPCAPI_enable_batch_create or $config->RPCAPI_enable_add_batch_job ) {
$log->info('Enabling add_batch_job method');
$router->connect("add_batch_job", {
handler => $handler,
action => "add_batch_job"
});
$router->connect("batch_create", {
handler => $handler,
action => "batch_create"
});
}
my $dispatch = JSON::RPC::Dispatch->new(
router => $router,
);
my $rpcapi_app = sub {
my $env = shift;
my $req = Plack::Request->new($env);
my $res = {};
my $content = {};
my $json_error = '';
try {
my $json = $req->content;
$content = decode_json($json);
} catch {
$json_error = (split /at \//, $_)[0];
};
if ($json_error eq '') {
my $errors = $handler->jsonrpc_validate($content);
if ($errors ne '') {
$res = Plack::Response->new(200);
$res->content_type('application/json');
$res->body( encode_json($errors) );
$res->finalize;
} else {
local $log->context->{rpc_method} = $content->{method};
$res = $dispatch->handle_psgi($env, $env->{REMOTE_ADDR});
my $status = Zonemaster::Backend::Metrics->code_to_status(decode_json(@{@$res[2]}[0])->{error}->{code});
Zonemaster::Backend::Metrics::increment("zonemaster.rpcapi.requests.$content->{method}.$status");
$res;
}
} else {
$res = Plack::Response->new(200);
$res->content_type('application/json');
$res->body( encode_json({
jsonrpc => '2.0',
id => undef,
error => {
code => '-32700',
message => 'Invalid JSON was received by the server.',
data => "$json_error"
}}) );
$res->finalize;
}
};
builder {
enable "Plack::Middleware::ReverseProxy";
mount "/" => $rpcapi_app;
};