Mar 152012
 

I started developing Perl REST API’s last year. I found very little useful information on the web or in books. I wanted to find out how to develop a REST server in Perl but everything I found was very high level or only covered how to develop clients in various languages. After a lot of research and trial and error I managed to develop my first REST server API. It’s been running for over 7 months now in a production environment without any problems. I thought it would be useful for those out there to have a basic template to start from as it would have helped me in the beginning. I have to admit I mainly use the GET method. I haven’t quite worked out how to receive a resource ID from a POST request. If anyone knows how to do this or works it out I would really appreciate if you would let me know. The same with PUT and DELETE. I haven’t quite worked out how to create resources, view them and delete them.

In my example below I created a basic CGI script called “rest” and it looks as follows:


#!/usr/bin/perl -w

use strict;
use warnings;
use CGI '3.30', ();
use CGI::Carp qw( fatalsToBrowser );

my $apititle = 'REST Server API Example';
my $apistyle = '/stylesheets/rest.css';

my $q = CGI->new;

sub GET($$) {
my ($path, $code) = @_;
return unless $q->request_method eq 'GET' or $q->request_method eq 'HEAD';
return unless $q->path_info =~ $path;
$code->();
exit;
}

sub POST($$) {
my ($path, $code) = @_;
return unless $q->request_method eq 'POST';
return unless $q->path_info =~ $path;
$code->();
exit;
}

sub PUT($$) {
my ($path, $code) = @_;
return unless $q->request_method eq 'PUT';
return unless $q->path_info =~ $path;
$code->();
exit;
}

sub DELETE($$) {
my ($path, $code) = @_;
return unless $q->request_method eq 'DELETE';
return unless $q->path_info =~ $path;
$code->();
exit;
}

eval {
# No arguments provided
GET qr{^$} => sub {
print $q->header(-status=>200, -type=>'text/html');
print $q->start_html(-title=>$apititle, -style=>$apistyle);
print $q->h1('Possibly some nice documentation goes here.');
print $q->end_html();
};

GET qr{^/id/(\d{1,5})$} => sub {
print $q->header(-status=>200, -type=>'text/html');
print $q->start_html(-title=>$apititle, -style=>$apistyle);
print $q->h1('Your ID is '.$1);
print $q->end_html();
};

# Unmatched REST
GET qr{^/(.+)$} => sub {
# Nothing handles this, throw back a standard 404
print $q->header(-status=>404, -type=>'text/html');
print $q->start_html(-title=>$apititle, -style=>$apistyle);
print $q->h1('Nothing has been matched or the arguments are invalid.');
print $q->end_html;
};

exit;
};

if ($@) {
# Handle errors
if (ref $@ and reftype $@ eq 'HASH') {
my $ERROR = $@;
print $q->header(-status=>$ERROR->{status}, -type=>'text/html');
print $q->h1($ERROR->{title});
print $q->p($ERROR->{message}) if $ERROR->{message};
print $q->end_html;
}

# Handle anything else
else {
# Nothing handles this, throw back a standard 404
print $q->header(-status=>404, -type=>'text/html');
print $q->start_html(-title=>$apititle, -style=>$apistyle);
print $q->h1('Nothing has been matched or the arguments are invalid.');
print $q->end_html;
}
exit;
}

I’m hoping this will be quite self explanatory as a base template but if you have any questions feel free to ask me. This REST API will output a page in text/html format but in a normal scenario would you output text/xml or application/json and format it accordingly. It’s just easier for the sake of this example to just keep it simple.

Examples of what this would look like from the browser:

http://1.1.1.1/cgi-bin/rest <- manual
http://1.1.1.1/cgi-bin/rest/id/100 <- display ID 100

Any suggestions, improvements or comments are most welcome.

Kind regards,
Mike

  One Response to “Perl REST server example”