Web services WSDL SOAP

Hi

I need to create a new web-service by using php. And I need to use SOAP RPC/encoded for implementing this. I also need to authenticate the soap request using soap header information. Before doing main task that I have created a WSDL file, client and server files using php.

I have managed to send the soap request with header. But I am unaware of using the header information in the server side. That is I don’t know how to check the header value is correct or not.

And I got error while I have setting “must-understand” to 1 or true. The error is “Header not understood”.

I am listing our WSDL, soap request, client and server here.

Please guide me to create a good web service with authentication using soap headers.

Thanks in advance

Dipu

WSDL

<?xml version="1.0" encoding="ISO-8859-1"?>
<definitions 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" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://localhost/dipu/webservices/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://localhost/dipu/webservices/">
<types>
<xsd:schema targetNamespace="http://localhost/dipu/webservices/">
<xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<xsd:import namespace="http://schemas.xmlsoap.org/wsdl/"/>
</xsd:schema>
</types>
<message name="getCatalogEntryRequest">
<part name="catalogId" type="xsd:string"/>
<part name="catalogId2" type="xsd:string"/>
</message>
<message name="getCatalogEntryRequestHeader">
<part name="username" type="xsd:string"/>
</message>
<message name="getCatalogEntryResponse">
<part name="Result" type="xsd:string"/>
</message>
<portType name="CalculatorPortType">
<operation name="getCatalogEntry">
<documentation>adds two string values and returns the result</documentation>
<input message="tns:getCatalogEntryRequest"/>
<output message="tns:getCatalogEntryResponse"/>
</operation>
</portType>
<binding name="CalculatorBinding" type="tns:CalculatorPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getCatalogEntry">
<soapperation soapAction="http://localhost/dipu/webservices/#getCatalogEntry" style="rpc"/>
<input>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/dipu/webservices/"/>
<soap:header message="tns:getCatalogEntryRequestHeader" part="username" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/dipu/webservices/" />
</input>
<output>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/dipu/webservices/"/>
</output>
</operation>
</binding>
<service name="Calculator">
<port name="CalculatorPort" binding="tns:CalculatorBinding">
<soap:address location="http://localhost/study/webservices/soapwithheader/wsdl_server2.php"/>
</port>
</service>
</definitions>

SOAP Request

<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://localhost/dipu/webservices/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ns2="http://namespace.example.com/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Header>
<ns2:username>dipu</ns2:username>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:getCatalogEntry>
<catalogId xsi:type="xsd:string">catalog1</catalogId>
<catalogId2 xsi:type="xsd:string">catalogTest111</catalogId2>
</ns1:getCatalogEntry>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Client File

<?php
ini_set("soap.wsdl_cache_enabled", "0");
$client = new SoapClient("catalog.wsdl",array('trace' => 1 ));
$catalogId='catalog1';
$functions=$client->__getFunctions();
echo '<pre>';
print_r($functions);


//	$soapHeader=new SoapHeader('http://soapinterop.org/echoheader/','username','hello world');
// $response = $client->getCatalogEntry('catalog1','catalogTest111', $soapHeader);
/*$bodyArr	= array('catalog1', 'catalogTest111');
$response = $client->__soapCall('getCatalogEntry', $bodyArr,NULL,$soapHeader,NULL);	 */
//	 echo '--'.$client->__getLastRequest().'--';
$ns = 'http://namespace.example.com/';
//Body of the Soap Header.
$header = new SOAPHeader($ns, 'username', 'dipu');
$testArr	= array('catalogId'=>'catalog1','catalogId2'=>'catalogTest111');	
$response=$client->__soapCall("getCatalogEntry",$testArr,NULL, $header);
//Create Soap Header.
echo $client->__getLastRequest();
//echo $client->__getLastRequestHeaders();

echo $response;
?>

Server File

<?php
function getCatalogEntry($catalogId,$catalogId2) {
if($catalogId=='catalog1')

return "<HTML>
<HEAD>
<TITLE>Catalog</TITLE>
</HEAD
<BODY>
<p> </p>
<table border>
<tr><th>CatalogId</th>
<th>Journal</th><th>Section
</th><th>Edition</th><th>
Title</th><th>Author</th>
</tr><tr><td>catalog1</td>
<td>IBM developerWorks</td><td>
XML</td><td>October 2005</td>
<td>JAXP validation</td>
<td>Brett McLaughlin</td></tr>
<tr><td>$catalogId2</td>
<td>IBM developerWorks</td><td>
XML</td><td>October 2005</td>
<td>JAXP validation</td>
<td>Brett McLaughlin</td></tr>
</table>
</BODY>
</HTML>";

elseif ($catalogId='catalog2')

return "<HTML>
<HEAD>
<TITLE>Catalog</TITLE>
</HEAD
<BODY>
<p> </p>
<table border>

<tr><th>CatalogId</th><th>
Journal</th><th>Section</th>
<th>Edition</th><th>Title
</th><th>Author
</th></tr><tr><td>catalog1
</td><td>IBM developerWorks</td>
<td>XML</td><td>July 2006</td>
<td>The Java XPath API
</td><td>Elliotte Harold</td>
</tr><tr><td>$catalogId2
</td><td>IBM developerWorks</td>
<td>XML</td><td>July 2006</td>
<td>The Java XPath API
</td><td>Elliotte Harold</td>
</tr>
</table>
</BODY>
</HTML>";
}

ini_set("soap.wsdl_cache_enabled", "0");
$server = new SoapServer("catalog.wsdl");
$server->addFunction("getCatalogEntry");

$server->handle();

?>

Hi crdipu, welcome to the forums,

I’m bushed right now but I’ll try to take a look at this as soon as I can tomorrow.

Hi Mittineague,

Thank you for your reply. I hope your suggestion will help me. I am also trying to find out the same. If I get the answer, I will post it.

Dipu

:lol: That looks a lot lot like an O’Reilly tutorial I did a while ago :wink:

I’ll fool with it some more in a bit. But one thing I noticed is that when the code was formatted for the article it mangled the closing head tags in the server.php file i.e. </HEAD

And I’m not sure if it makes a difference, but I changed all my HTML tag names to lowercase.

Everything seems to be “working” after I made a few changes.
I changed a few filenames to point to my localhost install.
I fixed the broken head tags
I changed soapperation to soap:operation in the wsdl file.

and got

Hi Mittineague,

                      Thank you for the reply. I also managed to get the same result, but my problem is "how to using the soap headers in the soap request". To use the soap header, I have added a message in the wsdl that is
<message name="getCatalogEntryRequestHeader">
<part name="username" type="xsd:string"/>
</message>

, also add some soap header information in the binding part of wsdl.

<soap:header message="tns:getCatalogEntryRequestHeader" part="username" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/dipu/webservices/" />

                       In the soap-client  I have passed a soap header, but I don't know how can I use the header information.
<SOAP-ENV:Header>
<ns2:username>dipu</ns2:username>
</SOAP-ENV:Header>
                       I don't know is it a right way to send and process soap header information, please suggest alternative ways, if I am in wrong way.

                        I hope your suggestion will help me.

Thanks in advance

Dipu

Sorry to have been gone, I got swamped all of a sudden for a couple of days.

I don’t have extensive experience with using SOAP, so I don’t know what alternatives might be better than others for what uses. But it seems the headers are getting sent OK the way you’re doing it.

What in particular are you wanting to do? Have the server script check for headers from the client script?

Hi Mittineague,

                      Thank you for your reply. I have manged to solve the problem by modify the WSDL , server file and the client file. Now It is able to send and manipulate the soap header information.

Dipu

WSDL FIle


<?xml version ='1.0' encoding ='UTF-8' ?>
<definitions name='SayHello' targetNamespace='urn:SayHello'
xmlns:tns='urn:SayHello'
xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/'
xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'
xmlns='http://schemas.xmlsoap.org/wsdl/'>

<message name='getHelloRequest'>
<part name='name' type='xsd:string'/>
</message>

<message name='validateRequest'>
<part name='username' type='xsd:string'/>
<part name='password' type='xsd:string'/>
</message>

<message name='validateResponse'>
<part name='testReturn' type='xsd:string'/>
</message>

<message name='getHelloResponse'>
<part name='Result' type='xsd:string'/>
</message>

<portType name='SayHelloPortType'>
<operation name='getHello'>
<input message='tns:getHelloRequest'/>
<output message='tns:getHelloResponse'/>
</operation>
<operation name='validate'>
<input message='tns:validateRequest'/>
<output message='tns:validateResponse'/>
</operation>
</portType>

<binding name='SayHelloBinding' type='tns:SayHelloPortType'>
<soap:binding style='rpc'
transport='http://schemas.xmlsoap.org/soap/http'/>
<operation name='getHello'>
<soap:operation soapAction='urn:SayHello#getQuote'/>
<input>
<soap:body use='encoded' namespace='urn:SayHello'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</input>
<output>
<soap:body use='encoded' namespace='urn:SayHello'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</output>
</operation>

<operation name='validate'>
<soap:operation soapAction='urn:SayHello#getQuote'/>
<input>
<soap:body use='encoded' namespace='urn:SayHello'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</input>
<output>
<soap:body use='encoded' namespace='urn:SayHello'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</output>
</operation>
</binding>

<service name='SayHelloService'>
<port name='SayHelloPort' binding='SayHelloBinding'>
<soap:address location='URL to your server location'/>
</port>
</service>
</definitions>

SOAP Request


<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
	xmlns:ns1="urn:SayHello" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="urn:example.org/auth"
	xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
	SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
	<SOAP-ENV:Header>
		<ns2:validate>
			<username>username</username>
			<password>password</password>
		</ns2:validate>
	</SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<ns1:getHello>
			<name xsi:type="xsd:string">catalog1</name>
		</ns1:getHello>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Server file


<?php

class SayHello {
public function getHello($inmessage) {
return "Hello $inmessage!";
}
public function validate($username,$password) {
	if($username!='username' || $password!='password'){
		 throw new SOAPFault("Incorrect username and password combination.", 401);
	}

}

} //end class
ini_set("soap.wsdl_cache_enabled", "0");
$server = new SoapServer("test_class.wsdl");
$server->setClass("SayHello");
$server->handle();
$functions=$server->getFunctions();

?>


Client File


<?php
  ini_set("soap.wsdl_cache_enabled", "0");
  $client = new SoapClient("test_class.wsdl",array('trace' => 1 ));
  $catalogId='catalog1';
  $functions=$client->__getFunctions();
  echo '<pre>';
  print_r($functions);


class SOAPAuth {
    public $username;
    public $password;

    public function __construct($username, $password) {
        $this->username = $username;
        $this->password = $password;
    }
}
	$ns = 'http://namespace.example.com/';
	//Body of the Soap Header.
	if(@$_GET['username']!='')$username	=$_GET['username'];else $username	= 'username';
	if(@$_GET['password']!='')$password	=$_GET['password'];else $password	= 'password';

	$auth = new SOAPAuth($username,$password);
	$header = new SOAPHeader('urn:example.org/auth', 'validate', $auth);
	$testArr	= array('testString'=>'catalog1');
try{
	$response=$client->__soapCall("getHello",$testArr,NULL, $header);
	

	echo $client->__getLastRequest();
   print_r($response);
}catch (SOAPFault $exception) {
	echo '<pre>';
	print_r($exception);
}
?>