资料收集站

SDL

Tuesday
Jan 06th
Text size
  • Increase font size
  • Default font size
  • Decrease font size

Web Services with NuSOAP

By S.D. Campbell

September 10, 2002

 

Intended Audience
Introduction
Web Services and SOAP
SOAP Messages
Using the NuSOAP toolkit
  • Developing a Server
  • Developing a Client
    Summary
    Sample Scripts
    About the Author

    Intended Audience

    This article is intended for the experienced PHP programmer, who is interested in developing web service with SOAP using a PHP-based toolkit.

    Readers interested in more information on SOAP and web services should refer to the following sites:

    Introduction

    My first experience working with SOAP and web services was not gentle. After dipping my toes in SOAP::Lite, a Perl module designed to make SOAP development simpler, I found myself needing to build a web service for a client using ASP.

    SOAP stands for Simple Object Access Protocol, but unfortunately, the early releases of Microsoft’s SOAP toolkit were anything but simple.

    Thankfully I discovered a solution that satisfied both my need for speed and simplicity: NuSOAP for PHP. I ported the web application from ASP to PHP and we were off to the races.

    The simplicity that NuSOAP (formerly SOAPx4) provides can be the difference between a successful web service rollout, and a disaster. It’s this simplicity that I’ll be looking at in this article.

    Web Services and SOAP

    Before diving into the toolkit proper, I’m going to take a little bit of time to explore the world of web services and SOAP.

    The concept of web services has grown from the desire to provide distributed computing abilities using a common infrastructure. XML and HTTP provide an ubiquitous platform for Remote Procedural Calls across the Internet. The simplicity of this combination, and its ease of implementation has given XML based web services a leg up over other similar technologies like CORBA, DCOM and Java RMI.

    SOAP is the current ‘killer app’ in the field of XML web services. SOAP and its supporting technologies like WSDL and UDDI are all based on the combination of XML transmitted over HTTP. SOAP provides a simple and flexible means of transmitting data, function calls, return values and other programming constructs between distributed platforms and various languages.

    The strength of web services is the ability to quickly publish interfaces to legacy systems, and to provided extended functionality to software and devices that would lack the resources for that functionality on their own.

    Web services are quickly becoming the foundation for a paradigm shift on the web, and are driving both Sun’s J2EE platform and Microsoft’s .Net platform.

    SOAP Messages

    SOAP is all about messages. A client transmits a service request and a server replies with either a response or a fault. Each of these possible transactions is a SOAP message, and all SOAP messages consist of an envelope with a Body, and an optional Head.

    Consider the following service request:

    POST /ws/taxCalc.php HTTP/1.1
    SOAPAction
    urn:soap-whytewolf-ca:taxcalc#taxCalc
    Content-Typetext/xml
    Content
    -Length557
    User
    -AgentkSOAP/1.0
    Host
    www.whytewolf.ca

    <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                       
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                       
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
                       
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
     <
    SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
      <
    taxCalc xmlns="urn:soap-whytewolf-ca:taxcalc" id="o0" SOAP-ENC:root="1">
       <
    rate xmlns="" xsi:type="xsd:string">7</rate>
       <
    sub xmlns="" xsi:type="xsd:string">856</sub>
      </
    taxCalc>
     </
    SOAP-ENV:Body>
    </
    SOAP-ENV:Envelope>


    The SOAP-ENV:Envelope tag is the request’s envelope root element. Inside that element is the SOAP-ENV:Body element which will contain the service request. Each service request will consist of an element indicating the name of the function being called (in this case taxCalc) and the contents of that tag will be tags representing the parameters being passed to the function.

    Using the example above as a guide we can see that out function has a signature something like (shown in UML notation):

    taxCalc(rate:stringsub:string):float

    The web service provider will accept the SOAP request, parse it, marshal the data and pass it to the requested function. The function will do its thing, and may or may not return some sort of response. The following is the response generated by our taxCalc() service:

    HTTP/1.1 200 OK
    Date
    Mon12 Aug 2002 01:31:10 GMT
    Server
    Apache/1.3.14 (Unix
    X-Powered-ByPHP/4.0.6
    Status
    200 OK
    Connection
    Close
    Content
    -Length510
    Content
    -Typetext/xmlcharset=UTF-8

    <?xml version="1.0"?>


    <
    SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
      
    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:si="http://soapinterop.org/xsd">
    <
    SOAP-ENV:Body>
    <
    taxCalcResponse>
    <
    noname xsi:type="xsd:float">915.92</noname>
    </
    taxCalcResponse>
    </
    SOAP-ENV:Body>
    </
    SOAP-ENV:Envelope>


    As you can see, again out message is contained within a SOAP-ENV:Envelope. This time the contents of the Body are an element called noname, of type xsd:float with a value of 915.92—the calculated total of our purchase of $856 with a 7% surcharge.

    What if there’s a problem? There would be no point in calculating a total based on a negative tax rate. In this case our service should indicate that there’s a problem should it receive a zero or negative tax rate. SOAP allows us to generate what is known as a SOAP Fault to indicate errors. Every fault contains four elements:

    • faultcode – The type of fault. It must be one of either Client, Server, MustUnderstand or VersionMismatch. Required.
    • faultstring – An indication of what the problem is. Required.
    • faultactor – What service caused the fault. Usually used in service ‘pipelining’. Optional.
    • faultdetail – Detailed information about the fault. Optional.
    Using this information a client application should be able to report to the user what error occurred and how to fix it.

    A SOAP Fault message is provided below:

    HTTP/1.1 200 OK
    Date
    Mon12 Aug 2002 01:32:12 GMT
    Server
    Apache/1.3.14 (Unix
    X-Powered-ByPHP/4.0.6
    Status
    500 Internal Server Error
    Connection
    Close
    Content
    -Length607
    Content
    -Typetext/xmlcharset=UTF-8

    <?xml version="1.0"?>


    <
    SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
      
    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:si="http://soapinterop.org/xsd">
    <
    SOAP-ENV:Body>
    <
    SOAP-ENV:Fault>
    <
    faultcode>Client</faultcode>
    <
    faultactor></faultactor>
    <
    faultstring>Must supply a non-zero tax rate.</faultstring>
    <
    faultdetail></faultdetail>
    </
    SOAP-ENV:Fault>
    </
    SOAP-ENV:Body>
    </
    SOAP-ENV:Envelope>


    This fault indicates that the error originates with the client—incorrect data has been passed to the server in the form of a zero or negative tax rate.

    Using the NuSOAP toolkit

    NuSOAP is one of several toolkits available for PHP developers who want to work with SOAP services. What drew me to it was the simplicity of installation—you only need to include the library in your script to create a web service. While there is some missing functionality, and the documentation could be more complete, NuSOAP has ease of use as its key advantage over other PHP solutions. In my estimation Dietrich Ayala, the developer of NuSOAP has done an excellent job.

    As I mentioned before the requirement for any NuSOAP based client or server is the nusoap.php file, downloadable from the website or from http://dietrich.ganx4.com/download.php?url=/nusoap/downloads/nusoap-0.6.1.zip directly. The zip file contains nusoap.php and all relevant documentation. Place the library in a directory accessible by your PHP files, and you’re ready to rock and roll.

    Developing a Server

    The first step in developing a server that will export its functions as web services is to develop those functions. Our taxCalc() function is pretty simple; take a tax rate and a subtotal and generate a total. The basic functionality is shown below:

    // Return the generated total for the purchase.
    function taxCalc ($rate=0$sub=0){     
        return ((
    $rate 100) * $sub) + $sub
    }


    To turn this into a web service we need to add a few lines to the top of the script:

    require_once('nusoap.php'); 
    $server = new soap_server;
    $server->register('taxCalc');


    First we include all the functionality required from the nusoap.php library using require_once(). Then we create a new SOAP Server and register the function we’re publishing with the server.

    Now that the service is registered we need to set it to run unattended using the HTTP transport mechanism. This is accomplished with the following code at the bottom of the script:

    $server->service($_SERVER['HTTP_RAW_POST_DATA']);
    exit();


    As can be seen we tell the server to run using the HTTP_RAW_POST_DATA server->service(), and then exit to ensure we don’t send any troublesome headers or HTML.

    All that’s missing from our service is fault generation. I want to be able to indicate to the client application when a zero or negative tax rate, or when a zero or negative subtotal is sent to my service. To do this I need to generate a SOAP Fault.

    NuSOAP makes this easy through the use of the soap_fault Class. The class constructor takes four parameters, the faultcode, faultactor, faultstring and faultdetail. To return a fault indicating an incorrect tax rate we would use the following code:

    return new soap_fault(
                
    'Client''',
                
    'Must supply a positive, non-zero tax rate.',''
            
    );


    Here we’re indicating the faultcode and faultstring, but leaving faultactor and faultdetail blank.

    Developing a Client

    The joy of distributed web services is that our client application doesn’t need to reside on the same computer as our server—or even need to use the same language. Seeing as we’re talking about NuSOAP and PHP however, I’m going to develop a client for the taxCalc() service using PHP and install it on the same box.

    Our client will have to take a tax rate and subtotal from the user, and the easiest way to do this is use a HTML form. I’ve elected to make life a wee bit more difficult and simply use a GET request with the needed data in the query string. Either way our client code will look the same.

    Again we start by calling the nusoap.php library using require_once(). We then build the parameter list and the values to be passed in. This can be accomplished by using an associative array:

    $param = array('rate'=>$_GET['rate'],'sub'=>$_GET['sub']);



    $client = new soapclient('http://www.whytewolf.ca/ws/taxCalc.php');

    Now the client object is ready to use. We invoke a service by using the call() method of our client object, and pass it the name of the function we’re calling and the paramter array we created earlier. As can be seen below, we need to capture the response from $client->call():

    $response $client->call('taxCalc'$param);

    If a fault has occurred the client object’s fault property will be set. Under these circumstances we can access any of the four fault fields through their corresponding properties in the client object like so:

    if($client->fault){
        echo 
    "FAULT:  <p>Code: {$client->faultcode} <br />";
        echo 
    "String: {$client->faultstring} </p>";


    To see the taxCalcClient at work use the following URL to get a valid response:

    http://www.whytewolf.ca/ws/taxCalcClient.php?rate=7&sub=856
    or this one to capture a fault in action:

    http://www.whytewolf.ca/ws/taxCalcClient.php?rate=-7&sub=856

    Summary

    SOAP and web services are growing more and more popular as support for various languages and development environments increase. Many web application projects start off as proof-of-concept prototypes however, and simple to use languages like PHP and SOAP toolkits like NuSOAP allow for faster development, deployment and consumption of web services.

    Sample Scripts

    Listing 1 – taxCalc.php Server

    <?php
    /**
    * taxCalc.php
    * An example PHP script which uses NuSOAP to provide a
    * tax calculator function.
    *
    * Created on August 7, 2002, 6:11 PM
    * @author  Sean Campbell
    * @version 1.0
    */

    /* Include the NuSOAP library. */
    require_once('nusoap.php'); 

    /* Create a new SOAP server instance. */
    $server = new soap_server;

    /* Register the taxCalc function for publication. */
    $server->register('taxCalc'); 

    /**
    * Calculates the total (including tax) for a purchase based on the
    * rate and subtotal provided.
    *
    * @param string $rate          The tax rate in percent.
    * @param string $sub           The subtotal for the purchase.
    *
    * @return float $total            The total for the purchase.
    *
    * @author  Sean Campbell
    * @version 1.0
    */
    function taxCalc ($rate$sub)
    {
        if (
    $rate == '' || $rate <= 0) {
            
    /* Return a SOAP fault indicating a negative or
             * zero tax rate was transmitted. */
            
    return new soap_fault(
                
    'Client''',
                
    'Must supply a positive, non-zero tax rate.',''
            
    );
        }

        if (
    $sub == '' || $sub <= 0) {
            
    /* Return a SOAP fault indicating a negative or
         * zero subtotal was transmitted. */
            
    return new soap_fault(
                
    'Client''',
                
    'Must supply a positive, non-zero subtotal.'''
            
    );
        }
        
        
    /* Return the generated total for the purchase. */
        
    return (($rate 100) * $sub) + $sub



    /* Begin the HTTP listener service and exit. */
    $server->service($_SERVER['HTTP_RAW_POST_DATA']);
    exit();
    ?>


    Listing 2 – taxCalcClient.php Client

    <html>
    <
    head>
    <
    title>Tax calculator Client</title>
    </
    head>
    <
    body>
    <
    h1>Tax calculated:</h1>
    <?
    php
    /**
    * taxCalcClient.php
    * An example PHP script which uses NuSOAP to access
    * a tax calculator function.
    *
    * Created on August 7, 2002, 6:11 PM
    * @author  Sean Campbell
    * @version 1.0
    */

    /* Include the NuSOAP library. */
    require_once('nusoap.php');

    /* Initialize the client's parameter list. */
    $param = array('rate' => $_GET['rate'], 
                   
    'sub' => $_GET['sub']
                   );

    /* Create a new client by providing the endpoint to the
    * constructor. */
    $client = new soapclient(
                        
    'http://www.whytewolf.ca/ws/taxCalc.php'
                        
    );

    /* Call the taxCalc() function, passing the parameter list. */
    $response $client->call('taxCalc'$param);

    /*  handle any SOAP faults. */
    if ($client->fault) {
        echo 
    "FAULT: <p>Code: {$client->faultcode}<br />";
        echo 
    "String: {$client->faultstring}";
    } else {
        echo 
    "$$response;
    }
    ?>
    </body>
    </html>


    About the Author

    Sean's consulting company, Whyte.Wolf, provides small business with the know-how they need to move into wireless and web services. He is a Senior Consultant with ContractBank (http://www.contractbank.com/CWIC) and heads the Web Development program at Applied Multimedia Training Centers in Calgary, Alberta.
  • Comments (0)Add Comment

    Write comment

    busy
     

    Google 搜索

    在线用户

    We have 84 guests online