Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked

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; }

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.

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 "/details" contains the 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.

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

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1039797]
Approved by davido
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (1)
As of 2017-05-01 04:22 GMT
Find Nodes?
    Voting Booth?
    I'm a fool:

    Results (544 votes). Check out past polls.