WebServices, HTTPObject, XML, and T3D.
by Vincent BILLET · 08/09/2010 (12:44 am) · 2 comments
This ressource give some code example to handle a WebService for T3D 1.1 using XML. It explains and give example to handle XML using HTTPObject.
First, let's take a simple WebService written in PHP. This simple WebService have 3 functionnalities :
* Multiple parameters requests (Login)
* Single record request (AccountInfo)
* A Listing (Connected)
You can copy/paste this simple php code. This code is not the subject of this ressource. It is only here to illustrate the T3D code.
Now, let's go to Torque :
1) You have to fix the engine.
2) You have to write WebService Client.
Fix for T3D 1.1 Beta 2
in httpObject.cpp , line 174 : Comment this line :
in httpObject.cpp , line 366 : Comment these lines to make the code looks like this :
The WebService Client
The Following code is divided in 3 parts :
PART1 : Test functions, to allow you a quick test from console
PART2 : WebService - General purpose. That's the main object of this ressource. This part gives you useful functions to build your WebService client.
PART3 : Example WebService Methods. These methods show you how to handle XML requests and answers.
To Create your own WebService Methods, you need to create one "caller" method, and one "callback" method on HTTPObject.
In the "caller" method (e.g. XMLLogin), you need to use :
In this callBack method, you can use the following functions :
Enjoy! Hopping it will help you to build WebServices clients for T3D.
Edit : Added OnDNSFailed, onConnectFailed functions.
First, let's take a simple WebService written in PHP. This simple WebService have 3 functionnalities :
* Multiple parameters requests (Login)
* Single record request (AccountInfo)
* A Listing (Connected)
You can copy/paste this simple php code. This code is not the subject of this ressource. It is only here to illustrate the T3D code.
<?php
function usrlogin($u,$p)
{
$result = "";
if (($u=="User1") && ($p=="pass1")) {$result.="<loginresult>SUCCESS</loginresult><userID>bac4e7cf41ae15478</userID>";} else
if (($u=="User2") && ($p=="pass2")) {$result.="<loginresult>AWAITING</loginresult>";} else
{ $result.="<loginresult>FAILURE</loginresult>"; }
return $result;
}
function accountinfo($uid)
{
if ($uid=="bac4e7cf41ae15478")
{
//Account exists
$result = "<exists>yes</exists>";
$result.="<LastName>DUPONT</LastName>";
$result.="<FirstName>Jhon Henri</FirstName>";
$result.="<mail>jhon@example.com</mail>";
$result.="<Score>18735</Score>";
} else
{
$result = "<exists>$uid does not exist.</exists>";
}
return $result;
}
function connected()
{
$result = "<ID>bac4e7cf41ae15478</ID><pseudo>Hey_Toto</pseudo><score>12547</score>";
$result.= "<ID>12345678902124528</ID><pseudo>Andrew</pseudo><score>541</score>";
$result.= "<ID>ba524c522ef524c45</ID><pseudo>Hello</pseudo><score>1257</score>";
$result.= "<ID>bcde1254585458521</ID><pseudo>Elric</pseudo><score>9875</score>";
$result.= "<ID>12542354856849447</ID><pseudo>Elminster</pseudo><score>1245</score>";
$result.= "<ID>12258525454542154</ID><pseudo>Johanna</pseudo><score>0</score>";
$result.= "<ID>11111111111111111</ID><pseudo>Vincent</pseudo><score>12584</score>";
$result.= "<ID>22222222222222222</ID><pseudo>Great_guy</pseudo><score>957</score>";
$result.= "<ID>33333333333333333</ID><pseudo>Funny</pseudo><score>5684</score>";
return $result;
}
$xml="<?xml version='1.0' encoding='ISO-8859-1'?>";
$xml.="<root>";
if ($_REQUEST["cmd"]=="login") {$xml.=usrlogin($_REQUEST["u"],$_REQUEST["p"]);} else
if ($_REQUEST["cmd"]=="accountinfo") {$xml.=accountinfo($_REQUEST["uid"]);} else
if ($_REQUEST["cmd"]=="connected") {$xml.=connected();}
$xml.="</root>";
echo($xml);
?>Notes : You can use multiple parameters on a query (see $_REQUEST). You need to create a "root" node to make your WebService server compliant with the following code (see HTTPObject::getXMLRoot). You also need to handle each command with "cmd" parameter (see HTTPObject::getXML).Now, let's go to Torque :
1) You have to fix the engine.
2) You have to write WebService Client.
Fix for T3D 1.1 Beta 2
in httpObject.cpp , line 174 : Comment this line :
// asciiEscapeTable[static_cast<U32>('&')] = true;(&'s Ascii Escape should be done in scripts)in httpObject.cpp , line 366 : Comment these lines to make the code looks like this :
// if(dStrcmp(query,"")) // object->get(Address, requirstURI, NULL); // else object->get(Address, requirstURI, query);// End of Fix.
The WebService Client
The Following code is divided in 3 parts :
PART1 : Test functions, to allow you a quick test from console
PART2 : WebService - General purpose. That's the main object of this ressource. This part gives you useful functions to build your WebService client.
PART3 : Example WebService Methods. These methods show you how to handle XML requests and answers.
//*********************************************************************
// PART1
// Test functions
//*********************************************************************
$WebServiceDNS = "www.someurl.com";
$WebServicePort = 80;
$WebServiceURL= $WebServiceDNS@":"@$WebServicePort;
$WebServicePath = "/";
$WebServiceApplication = "WebService.php";
function example_Login()
{
$WebService = new HTTPObject();
$WebService.init_http($WebServiceURL,$WebServicePath,$WebServiceApplication);
$WebService.XMLLogin("User1","pass1");
}
function example_Account()
{
$WebService = new HTTPObject();
$WebService.init_http($WebServiceURL,$WebServicePath,$WebServiceApplication);
$WebService.XMLUserAccount("bac4e7cf41ae15478");
}
function example_Connected()
{
$WebService = new HTTPObject();
$WebService.init_http($WebServiceURL,$WebServicePath,$WebServiceApplication);
$WebService.XMLConnected();
}
//*********************************************************************
// PART2
// WebService - General purpose
//*********************************************************************
//*********************************************************************
// Init
function HTTPObject::init_http(%this,%webserver,%webpath,%webapp)
{
%this.WebServer = %webserver;
%this.WebPath = %webpath;
%this.WebApp = %webapp;
%this.WebResp = "";
}
//*********************************************************************
// HTTPEvents
function HTTPObject::onLine(%this,%line)
{
%this.WebResp = %this.WebResp @ %line;
}
function HTTPObject::onDisconnect(%this)
{
%this.getXMLRoot();
eval(%this@"."@%this.callBack@"CallBack();");
%this.WebResp="";
}
function HTTPObject::onDNSResolved(%this)
{
echo("WebService : DNS Resolved");
}
function HTTPObject::onDNSFailed(%this)
{
error("Check your DNS configuration - (Try to ping "@$WebServiceDNS@")");
}
function HTTPObject::onConnectFailed(%this)
{
error("Unable to connect to "@$WebServiceURL@" - try to browse URL : http://"@$WebServiceURL@$WebServicePath@$WebServiceApplication);
}
//*********************************************************************
// Simple XML Handling
function HTTPObject::getXML(%this,%command,%callback)
{
%query = "cmd="@%command;
%script = %this.WebPath @ %this.WebApp;
%this.WebResp="";
if (%this.XMLData!$="") {%this.XMLData.delete(); }
%this.XMLData = new ScriptObject();
%this.callBack = %callback;
%this.get(%this.WebServer,%script,%query);
}
function HTTPObject::getXMLRoot(%this)
{
%startTag = "<root>";
%endTag = "</root>";
%startChar=0;
%xml = %this.WebResp;
%startTagOffset = strpos(%xml, %startTag, %startChar);
%startOffset = %startTagOffset + strlen(%startTag);
%endTagOffset = strpos(%xml, %endTag, %startOffset - 1);
if(%startTagOffset >= 0)
{
%this.XMLRoot=getSubStr(%xml, %startOffset, %endTagOffset - %startOffset);
} else {
%this.XMLRoot = "";
error("No XML Root : WebService answers must have a <root>...</root> node");
}
}
function HTTPObject::getXMLData(%this,%node)
{
%xml = %this.XMLRoot;
%startTag = "<" @ %node @ ">";
%endTag = "</" @ %node @ ">";
%startChar=0;
%ii = -1;
while (true)
{
%startTagOffset = strpos(%xml, %startTag, %startChar);
%startOffset = %startTagOffset + strlen(%startTag);
%endTagOffset = strpos(%xml, %endTag, %startOffset-1);
%startChar = %endTagOffset+strlen(%endTag);
%ii++;
if(%startTagOffset >= 0)
{
%this.XMLData.setFieldValue(%node@%ii,getSubStr(%xml, %startOffset, %endTagOffset - %startOffset));
} else {
%this.XMLData.setFieldValue("count_"@%node,%ii);
return;
}
}
}
//*********************************************************************
// Main XML functions
function HTTPObject::getXMLNode(%this,%node)
{
if (%this.XMLData.getFieldValue(%node@"0") $= "")
{
%this.getXMLData(%node);
}
return %this.XMLData.getFieldValue(%node@"0");
}
function HTTPObject::getXMLListNodeCount(%this,%node)
{
if (%this.XMLData.getFieldValue("count_"@%node) $= "")
{
%this.getXMLData(%node);
}
return %this.XMLData.getFieldValue("count_"@%node);
}
function HTTPObject::getXMLListNode(%this,%node,%line)
{
if (%this.XMLData.getFieldValue(%node@"0") $= "")
{
%this.getXMLData(%node);
}
return %this.XMLData.getFieldValue(%node@%line);
}
//*********************************************************************
// PART3
// Example WebService Methods
//*********************************************************************
// XML Login
function HTTPObject::XMLLogin(%this,%login,%pass)
{
%this.getXML("login&u="@%login@"&p="@%pass,"XMLLogin");
}
function HTTPObject::XMLLoginCallBack(%this)
{
%loginresult = %this.getXMLNode("loginresult");
%LoginOK = (%loginresult $= "SUCCESS");
%Awaiting = (%loginresult $= "AWAITING");
if (%LoginOK)
{
%this.logged=true;
%this.userID = %this.getXMLNode("userID");
// Account GUI
echo("Account GUI:"@%this.userID);
} else
if (%Awaiting)
{
%this.logged=false;
%this.userID = 0;
// Launch Awainting validation GUI
echo("Awaiting account GUI - Check your mail");
} else
{
%this.logged=false;
%this.userID = 0;
// Launch Login failure GUI
echo("Login Failure");
}
}
//*********************************************************************
// XML User Account
function HTTPObject::XMLUserAccount(%this,%userID)
{
%this.getXML("accountinfo&uid="@%userID,"XMLUserAccount");
}
function HTTPObject::XMLUserAccountCallBack(%this)
{
//Show User AccountGUI
if (%this.getXMLNode("exists")$="yes")
{
echo(%this.getXMLNode("LastName"));
echo(%this.getXMLNode("FirstName"));
echo(%this.getXMLNode("mail"));
echo(%this.getXMLNode("Score"));
} else
{
echo("Account does not exist.");
}
}
//*********************************************************************
// XML ConnectedUsers
function HTTPObject::XMLConnected(%this)
{
%this.getXML("connected","XMLConnected");
}
function HTTPObject::XMLConnectedCallBack(%this)
{
//Show Connected Users GUI
%num = %this.getXMLListNodeCount("ID");
if (%num$="") { echo("Nobody connected"); return; }
echo("Users Connected : "@%num);
// Browse each lines.
echo("user ID : pseudo : score");
for (%ii=0;%ii<%num ;%ii++ )
{
%id = %this.getXMLListNode("ID",%ii);
%pseudo = %this.getXMLListNode("pseudo",%ii);
%score = %this.getXMLListNode("score",%ii);
echo(%id@" : "@%pseudo@" : "@%score);
}
}To Create your own WebService Methods, you need to create one "caller" method, and one "callback" method on HTTPObject.
In the "caller" method (e.g. XMLLogin), you need to use :
%this.getXML(%query,%MyMethod);As defined in HTTPObject::onDisconnect you need to create a callback function called HTTPObject::MyMethodCallBack()
In this callBack method, you can use the following functions :
%value = %this.getXMLNode("MyXMLNode"); // Return a single node value
%value = %this.getXMLListNode("MyXMLNode",%lineNum); // Return the node of %lineNum (for grids)
%value = %this.getXMLListNodeCount("MyXMLNode"); // Return the Number of node in the XML response.Enjoy! Hopping it will help you to build WebServices clients for T3D.
Edit : Added OnDNSFailed, onConnectFailed functions.
About the author
#2
I don't think DNS errors comes from Apache.
08/11/2010 (10:05 am)
I edited this resource to make simple error's handling. If you have a DNS error, check your $WebServiceDNS : $WebServiceDNS = "www.someurl.com"; // With no http:// $WebServicePort = 80; // 80 in most cases $WebServiceURL= $WebServiceDNS@":"@$WebServicePort; $WebServicePath = "/"; // path of your application $WebServiceApplication = "WebService.php"; // WebService PHP
I don't think DNS errors comes from Apache.

Torque 3D Owner Jamie62
NDRC