There is an application that generates multiple records per day, containing different types of attributes like EmpName, EmpDesig etc. and stores it in JSON format. This application then needs to make a call towards external REST api to POST this data that is in JSON format. The external application will read the JSON file, parse it, and store each record in the PostgreSQL database. How do I write a REST api in Perl for this requirement? Do I need any Perl framework like Mojolicious or Catalyst or Perl modules like JSON, Rest::Client are enough for this requirement? Please suggest.
Asked
Active
Viewed 1,071 times
0
-
1See also [How can I make a JSON POST request with LWP?](https://stackoverflow.com/q/4199266/2173773) – Håkon Hægland Oct 23 '19 at 05:51
-
Your question seems slightly confused. That's probably because you're unclear on the terminology. I think you want to POST data **to** a REST API, not write a REST API. In that case, you don't need a framework, you just need an HTTP client like [LWP](https://metacpan.org/pod/LWP) and, probably, a [JSON encoder](https://metacpan.org/pod/JSON). – Dave Cross Oct 23 '19 at 08:13
-
I need to write a REST API, that will be used by the other application to POST data. The other application that will POST data will not be under my control. Though for testing, I will need a POST mechanism also, else how will I test it. – Manoj Agarwal Oct 23 '19 at 09:14
2 Answers
2
If you do want to use a framework, it'll simplify your code a lot.
You could do it with the Dancer framework in a single line:
perl -e 'use Dancer; any "/", sub{ warn to_dumper from_json request->body; return "ok" }; start'
However, this answer is just a start, it's not robust nor contains any checks.

Uncle Arnie
- 1,655
- 1
- 11
- 13
-
Thanks for your suggestion, I will definitely have a look into Dancer framework and dive further into it. – Manoj Agarwal Oct 24 '19 at 11:49
1
You don't strictly need a framework. It's easiest to get started with Plack::Request. The next step up would be adding a router like Router::Resource. Upgrading to a framework makes sense when you find this style of programming too tedious.
use Plack::Request qw();
use HTTP::Status qw(
HTTP_NO_CONTENT HTTP_NOT_FOUND HTTP_METHOD_NOT_ALLOWED
HTTP_UNSUPPORTED_MEDIA_TYPE HTTP_UNPROCESSABLE_ENTITY
HTTP_INTERNAL_SERVER_ERROR
);
use JSON::MaybeXS qw(decode_json);
use Syntax::Keyword::Try;
require IO::Handle;
use DBI qw();
require DBD::Pg;
my $app = sub {
my ($env) = @_;
my $req = Plack::Request->new($env);
return $req->new_response(HTTP_NOT_FOUND)->finalize
unless '/receive_json' eq $req->path_info;
return $req->new_response(HTTP_METHOD_NOT_ALLOWED)->finalize
unless 'POST' eq $req->method;
return $req->new_response(HTTP_UNSUPPORTED_MEDIA_TYPE)->finalize
unless $req->content_type =~ m'^application/.*json$';
my $body = do {
IO::Handle->input_record_separator(undef);
$req->input->getline;
};
my $json;
try {
$json = decode_json $body;
} catch {
warn "could not decode JSON: $@";
return $req->new_response(HTTP_UNPROCESSABLE_ENTITY)->finalize;
}
my $dbh;
try {
$dbh = DBI->connect(
"dbi:Pg:dbname=$ENV{PGDATABASE}",
$ENV{PGUSER},
$ENV{PGPASSWORD},
{pg_enable_utf8 => 1, RaiseError => 1}
);
} catch {
warn "could not connect to database: $@";
return $req->new_response(HTTP_INTERNAL_SERVER_ERROR)->finalize;
}
my $sth = $dbh->prepare(
'insert into sometable(EmpName, EmpDesig) values (?,?)'
);
try {
$sth->execute($json->{EmpName}, $json->{EmpDesig});
} catch {
warn "could not insert: $@";
return $req->new_response(HTTP_INTERNAL_SERVER_ERROR)->finalize;
}
return $req->new_response(HTTP_NO_CONTENT)->finalize;
};

daxim
- 39,270
- 4
- 65
- 132