How to implement the SOAP technology

written by: Emanuela Hedrick; article published: year 2006, month 07;


In: Root » Internet » APIs and Web Feeds » How to implement the SOAP technology

Dutch French Spanish Portuguese Italian German Japanese Chinese Korean Russian Arabic Bookmark and Share this Article

Like REST, implementing SOAP involves both generating requests and then handling the response. Whereas handling the SOAP response is similar to the REST result, generating the SOAP request is quite different.

Generating Requests

Unlike REST, it is rather uncommon to see requests generated manually, though it can still be done. Generally, SOAP requests are either generated with a generic tool (like NuSOAP or Pear:SOAP) or with an application-specific class or module. Manual generation is covered here (a good understanding of how it works will come in useful), as well as NuSOAP.

Application-specific tools are going to be ignored, for a couple reasons. By definition they are application specific, and therefore not very useful in this generic article. Secondly, the tools have varying interfaces and functionality levels, and in order to do the topic justice it would require an in-depth look. Finally, I am firmly of the opinion that if you can figure out how to make it work with NuSOAP (or raw, for that matter), you can get the application-specific tool to work too.

Manual Generation

Generating SOAP requests manually isn't too different from generating REST requests. The process of generating the request and actually transmitting it is split into two separate functions, for demonstrating purposes.

For generating the request itself, I have chosen to use a pregenerated string, and merely populate the required values at runtime. There are more complex options (such as creating the document within SimpleXML, or creating it from scratch each run), but they aren't really required:

functioncreateRequest($devkey, $action, $type, $keyword)
{
  $request = "<?xmlversion=\"1.0\" encoding=\" UTF-8\" standalone=\"no\"?>
<SOAP-ENV:Envelope
 xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"
 xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
 xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">
  <SOAP-ENV:Body>
    <devkey xsi:type=\"xsd:int\">$devkey</devkey>
    <action xsi:type=\"xsd:string\">$action</action>
    <type xsi:type=\"xsd:string\">$type</type>
    <keyword xsi:type=\"xsd:string\">$keyword</keyword>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>";
  return $request;
}

As you can tell, the function is just about as simple as it can get. Note that the variables haven't been URL-encoded; that's because they aren't being sent in the URL (sounds obvious, but it's also easy to miss).

Actually, calling the API to transmit the request involves borrowing some code from the first REST example, because the request will be sent raw this time.

functioncallSOAPAPI($data)
{
  $url ="http://library.example.com/api/soap/search";
  $url_info = parse_url($url);
  $host = $url_info[‘host'];
  $path = $url_info[‘path'];

I could have just populated the $host and $path variables at the start, but this should be clearer. In a production system, you could save a few CPU cycles by hardcoding these elements.

  $fp=fsockopen($host, 80);
  fputs($fp, "GET ". $path ."HTTP/1.1\r\n");
  fputs($fp, "Host: ". $host."\r\n");
  fputs($fp, "Accept: */*\r\n");
  fputs($fp, "Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n");
  fputs($fp, "Connection:close\r\n");
  fputs($fp, "Content-Type:application/soap+xml\r\n");
  fputs($fp, "Content-Length: ".strlen($data) . "\r\n\r\n");
  fputs($fp, "$data");

This block is nearly identical to the previous example. The previous example was a POST request, whereas this is a GET request, a change that will be dictated by whatever API you are working with. The Content-Type header is different to accurately reflect what you're sending and this time of course you have $data to send, so Content-Length won't be 0.

  $response="";
  while(!feof($fp))
  {
    $response.=fgets($fp, 128);
  }
  fclose($fp);
  list($http_headers,$http_content)=explode("\r\n\r\n", $response);
  return $http_content;
}

This section is also identical to the REST example. Wrapping both those functions to retrieve a response is only barely worth mentioning:

$request =createRequest('123', 'search', 'book','style);
$response= callSOAPAPI($request);

Wasn't too hard!

Unlike REST, you can't just use file_get_contents() to hit the API, because you need to send the XML body with the request. file_put_contents() wont work either, because you need the response (file_put_contents() returns an int), but there are other options. Pear (http://pear.php.net), for example, has a bunch of HTTP-specific functions that can take some of the headache of manually creating the request off your hands, but still allow you all the flexibility you get with manual creation.

Generation with NuSOAP

For anything other than a one-shot program, I would definitely recommend going with some sort of a SOAP module to make your coding life easier. Although, if you run into problems, tracking them down can be a bit of a pain. I like using a local development box during development, so should things start going awry I can use a packet sniffer to look at the request/response in its raw form.

Conceptually, using NuSOAP isn't too different from completing the task manually. The object is initialized, the payload is created, and the request is sent. The key difference here is that NuSOAP is doing all the dirty work.

require('../lib/nusoap.php');
$client =new soapclient("http://library.example.com/api/soap/wsdl/", true);

Here the $client object is created. Two options are available when creating a new soapclient: You can either specify the wsdl file for the service (and set the second parameter to true), or specify the endpoint for the call (and set the second parameter to false). Whenever possible, I like to use the wsdl file; the NuSOAP module can catch some of your mistakes that way, and it ensures that different request types all go to the correct endpoint.

$params =array(
  'devkey'  => '123',
  'action'  => 'search',
  'type'    => 'book',
  'keyword' => 'style'
);

Preparing the parameters for transmission is a bit easier than earlier methods.

$namespace= 'http://library.example.com';
$action = 'http://library.example.com/api/soap/search';
$method ="SearchRequest";
$result =$client->call($method,
  array(‘SearchRequest' => $params),
  $namespace, $action);

Finally, the last few parameters are set, and the call itself is made.

Handling the Response

Handling a response from a SOAP request is again not too different from the REST response—both are provided in similar XML formats. The SOAP response carries the additional Envelope and Body elements, but often present data in a similar manner within those elements. There is of course some variation between handling the response from a manual request and from a NuSOAP request. Both methods are presented here.

Manually Parsing the Response

Mimicking the output generated with the REST request uses similar code, with a few modifications for the encapsulation scheme used with SOAP.

echo"You searched for:{$xml->Body->LibrarySearchResponse->RequestInfo->
     keyword}<br>";

echo"Here are your{$xml->Body->LibrarySearchResponse->ResponseInfo-    >ResultCount}
     results<br>";
foreach($xml->Body->LibrarySearchResponse->ResponseInfo->Item AS &$item)
{
   echo "{$item->Title} by{$item->Author}<br>";
}

This will generate identical output as the REST request shown earlier. Note the different syntax used to acquire the search keyword. It isn't an attribute this time, so access is different.

Parsing the Response with NuSOAP

Accessing the object provided by NuSOAP is a little different from the methods used with SimpleXML, but the internal data structure is quite similar. Modifying the code to work with the NuSOAP object only takes a few moments.

echo"You searched for: ".
 $xml['Body']['LibrarySearchResponse']['RequestInfo']['keyword'] ."<br>";
echo"Here are your
 {$xml['Body']['LibrarySearchResponse']['ResponseInfo']['ResultCount']}
  results<br>";
foreach($xml['Body']['LibrarySearchResponse']['ResponseInfo']['Item']   AS &$item)
{
  echo "{$item[‘Title']} by{$item[‘Author']}<br>";
}

With NuSOAP, the internal data is accessed much the same way as an associative array, so rather than the OO method of using -> to access child elements, further array information is included. This element will output identically to the previous example.

SOAP is an effective method of querying APIs when the additional overhead is permissible. The encapsulation of all elements allows for easy reading, and variable scope within the request. Creating SOAP requests can be as easy as writing them out once, then just replacing key variables. Alternatively, it can also be accomplished by using a tool such as NuSOAP. Accessing the SOAP response can be accomplished in much the same manner as the REST response when the request has been completed manually. In the case of requests completed with NuSOAP, the access method is structurally identical, with only a few minor changes to the syntax used.

Disclaimer

1) E-articles is not responsible for the information contained by this article as well for any and all copyright infringements by authors and writers. E-articles is a free information resource. If you suspect this article for any copyright infringement, please read the terms of service and contact us to investigate the problem.
2) E-articles is not responsible for inaccuracies, falsehoods, or any other types of misinformation this article may contain and will not be liable for any loss or damage suffered by a user through the user's reliance on the information gained here.

link to this article