Jump to content

Perl does AJAX

Recommended Posts

Here we have a script that receives an AJAX POST, parses the request, and returns the appropriate data, in this case information about the directory that houses the calling document. Notice that it uses no libraries. CGI.pm doesn't handle AJAX very well (YMMV), and AJAX.pm is too complicated for a simple exercise like this (and most other applications as well). Here, the subroutine that parses the post data is generic enough that it can be used in any cgi context. It's also short and can even live in a "require" file.

#!/usr/bin/perlprint "Content-type: text/plain\n\n";sub main(){   readPostData() or print "foobar" and return;   for (my $i = 0; $NAMES[$i]; $i++){	  if ($NAMES[$i] eq "print"){printDirData($VALUES[$i]);}   }}# END main()sub readPostData(){ # a generic routine that can be copied and pasted with no changes   my $i;   my $buffer;   my @data;   read (STDIN, $buffer, $ENV {"CONTENT_LENGTH"}) or return 0;   @data = split (/&/, $buffer);   for ($i = 0; $data[$i]; $i++){	  ($NAMES[$i], $VALUES[$i]) = split (/=/, $data[$i]);	  $VALUES[$i] =~ tr/+/ /;	  $VALUES[$i] =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack ("C", hex ($1))/eg;   }   return 1;}# END readPostData()sub printDirData(){   my @list;   opendir MY_DIR, "." or print "Could not open directory" and exit;   @list = readdir (MY_DIR) or print "Could not read directory" and exit;   close (MY_DIR);   @list = grep(!/\.$/, @list);   for ($_[0]){#implicit matching used like switch	  /all/   and last;	  /files/ and @list = grep(-f, @list), last;	  /dirs/  and @list = grep(-d, @list), last;   }   @list = sort @list;   for (@list){print "$_\n";}}# END printDirectory()main();#end ajax.cgi

Here we have the matching HTML document with script. It's so generic it makes a useful model for any AJAX situation (though for simplicity's sake it only checks for returned errors, not broken pipe errors).

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html>	<head>	   <title>Ajax test</title>	</head>	<body> 	   <button onclick= "hPostData('print=all')">List all</button>	   <button onclick= "hPostData('print=files')">List files</button>	   <button onclick= "hPostData('print=dirs')">List directories</button>	   <br>	   <textarea id='myText' rows='43' cols='30'></textarea> 	   <script type="text/javascript">		  var hObj;		  function hPostData(myData) {			 hObj = null;			 var myURL = "ajax.cgi";			 if (hObj = getHObject()){				hObj.onreadystatechange = hStateChanged;				hObj.open ('POST', myURL, true);				hObj.send (myData);			 }else {alert ("Cannot get an HTTP object");}		  }		  function hStateChanged() { 			if (hObj.readyState == 4) {			   if (hObj.status == 200) {				  printResponse(hObj.responseText);			   }else{				  alert ('Sorry: ' + hObj.status);			   }			}		  }		  function getHObject() {			 var hObj = null;			 try {hObj = new XMLHttpRequest();}			 catch (e) {				try {hObj = new ActiveXObject('Msxml2.XMLHTTP');}				catch (e) {hObj = new ActiveXObject('Microsoft.XMLHTTP');}			 }			 return hObj;		  }		  function printResponse(myText) {			 var myTA = document.getElementById('myText');			 myTA.value = myText;		  }	   </script> 	</body> </html>

Remember: perl scripts do not usually copy and paste very well. The usual villain is newline/carriage return characters. If you do want to paste this one, if you get an error, you might try deleting all the end-of-lines and then simply hitting your return key to reinsert the proper end-of line code. Or, you could just retype the thing.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...