Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Web Services

by packetstormer (Monk)
on Jun 19, 2013 at 16:03 UTC ( #1039797=perlquestion: print w/ replies, xml ) Need Help??
packetstormer has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks

This question, like a lot of my questions, if more looking for suggestions that actual code problems.
I have been thinking about creating a small, simple web services script and any place I look for information/tutorial seems to suggest it as being quite difficult. I have a really simple and crude script below and I am looking for thoughts on why this type of approach is bad!
It is a simple process and the setup to return a JSON string.

Ideally I would create a backend DB with the auth details (for valid user API keys) and expand on the query/queries to return more attributes. My main concern is the method. Is this a really bad way to provide a web services service!? (Sitting on a standard Apache2 instance at the moment)

#!/usr/bin/perl use strict; use warnings; use DBI; use CGI; use JSON::XS; # Naively simple web service!? my $cgi = new CGI; my $auth_code = "XD9920399fldkkxzmfoJfkYYUS2"; my $lookup = $cgi->param("lookup"); my $client_key = $cgi->param("client_key"); my $print; # Expand this later to return unique error for each possible omission if ( (! defined $lookup) || (! defined $client_key) || ($client_key ne + $auth_code) ) { $print = encode_json {error => 'You must provide a lookup and vali +d client key'} } else{ my $dbh = new_dbh(); my $sth = $dbh->prepare("SELECT title,next_episode FROM watcher WHERE userid = ?"); $sth->execute($lookup); $print = encode_json $sth->fetchrow_hashref(); } print "Content-type: text/html\n\n"; # Send back the Json string print "$print"; sub new_dbh { my $db_driver = "mysql"; my $db_name = "shows"; my $db_host = "localhost"; my $db_port = "3306"; my $db_user = "root"; my $db_passwd = "xxxxxx"; my $dbh= DBI->connect("DBI:$db_driver:dbname=$db_name;host=$db_hos +t;port=$db_port", $db_user, $db_passwd,{RaiseError => 1, mysql_enable_utf8 => 1, }); $dbh->{TraceLevel} = 2; # disable when live return $dbh; }

Comment on Web Services
Download Code
Replies are listed 'Best First'.
Re: Web Services
by derby (Abbot) on Jun 19, 2013 at 16:27 UTC

    Bad? That really depends on your perspective. Let's say it's not production ready. There are two camps for web services -- SOAP and REST. SOAP has a huge learning curve while REST (IMHO) is a bit more accessible for beginners. Given your script above and the principles of REST, I would say you should

    • use path info for resource access (/id instead of lookup=id)
    • use HTTP headers to pass auth tokens
    • use HTTP methods to drive what to do with the resource (GET, POST, PUT, DELETE)
    • set the content type to application/json if your sending back json
    That should give you enough to chew on for a while.

    -derby
Re: Web Services
by bart (Canon) on Jun 19, 2013 at 18:57 UTC
    I can only see one thing obviously fishy in your script, and that is this line:
    print "Content-type: text/html\n\n";
    JSON is not HTML, so surely this is wrong. Not that many (or even any) clients would mind.
Re: Web Services
by creeble (Sexton) on Jun 20, 2013 at 01:45 UTC
    There's certainly nothing sick about it, save for the points derby and bart point out.

    "$print" is a bit redundant :)

    People quibble about GET, PUT, POST etc mapping to their logical functions for a true REST interface, but it really depends on what you expect your client to be able to understand. Everyone understands GET and POST, so I tend to use those exclusively (and still call it a REST-y interface).

    Putting the 'client_key' in a header might be considered ever-so-slightly safer, in that it won't appear in a URL (regardless of SSL use), but you could just as easily require that the data be submitted with a POST by checking the method.

    Is $lookup subject to SQL injection attack? I don't think so, if you're using a prepare() and parameter binding. But I could be wrong. In any case, that's something to look out for when writing a web service like this that uses a param() in a SQL statement.

Re: Web Services
by packetstormer (Monk) on Jun 20, 2013 at 11:07 UTC

    Thanks for the replies.

    I have query though (and I realise this might seem like a newbie query!) but if I was to use path info for resource access would I need to have a corresponding script in each directory on my webserver? That is, "/id" directory contains it's own id.pl "/details" contains the details.pl script?

      No, you do not. You could have it as /cgi-bin/script_name/id -- and then use CGI's path_info method to get the appropriate info. If you're really into it, I would recommend Dancer or Mojolicious over bare-bones CGI. One of the big wins for those two frameworks are the router DSL they provide that abstracts all that low-level path_info/param handling away.

      Also, since you're really at the beginning web developer stage, seek out a local Perl Mongers meeting for assistance.

      -derby
        Thanks derby - there is no Perl Mongers meet in my country though! I will struggle on!

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1039797]
Approved by davido
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (11)
As of 2015-07-30 14:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (271 votes), past polls