SOAP URL Domain Package for TclHTTPD
Description: SOAP package for Tcl. Provides remote procedure calls using the SOAP protocol over HTTP.
Keywords: Tcl,SOAP,Simple Object Access Protocol,XML,tclHTTPD

| # Tcl SOAP Server Utility Package |
The `SOAP::Domain` package provides a wrapper enabling the simple use of Tcl procedures as SOAP methods. The package is designed to operate with the tclhttpd web server but in principal could be converted to another server fairly easily. As an example of its use enter the following code and save as `soap1.tcl` in the custom subdirectory of the tclhttp server. (Alternatively source this script into a running server).
    package require SOAP::Domain

    namespace eval urn:tclsoap:Test1 {

       proc square {num} {
          if { [catch {expr $num + 0}] } {
             error "parameter num must be a number"
          }
          return [expr {$num * $num}]
       }

       SOAP::export square

    }

    SOAP::Domain::register -prefix /soap \
        -namespace urn:tclsoap:Test1 -uri urn:tclsoap:Test1
This block of code loads the SOAP server utilities (the SOAP::Domain package) and registers a handler for the /soap URL namespace with the http server. The effect of this is that any URL under /soap will be handled by SOAP::Domain::domain_handler. This procedure examines incoming SOAP requests and attempts to evaluate corresponding procedures in the specified namespace. By specifying a namespace we can isolate the soap procedures from any other procedures defined in the server. If we require an additional level of security we can specify a named slave interpreter rather than a namespace and then define our soap methods within the slave interpreter. We then define our SOAP method in a namespace (generally life is simpler if this is the same as the XML namespace). We also must publish the public methods. This is to prevent exposing Tcl internal commands like `exec` accidentally. We can test the above server by entering the following script to get a SOAP command in Tcl to use this service.
    % package require SOAP
    1.6
    % SOAP::create square \
               -uri urn:tclsoap:Test1 \
               -proxy http://localhost:8015/soap \
               -params {num integer}
    ::square
    % square 8
    64
Errors returned by the Tcl procedure are converted into SOAP Fault reply packets. According to the SOAP 1.1 specification the presence of a detail element under the Fault element is indicative of a failure in evaluating the body of the SOAP request. For errors thrown by the evaluated procedure this package generates a Fault packet and places the contents of the global errorInfo variable into the detail element. To illustrate this, if we evaluate the following in the server
    % square Hello
    SOAP-ENV:Client {parameter num must be a number}

    % SOAP::dump square
    <?xml version='1.0'?>
    <SOAP-ENV:Envelope
      xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
      xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
      xmlns:xsd="http://www.w3.org/1999/XMLSchema">
      <SOAP-ENV:Body>
        <SOAP-ENV:Fault>
          <faultcode>SOAP-ENV:Client</faultcode>
          <faultstring>parameter num must be a number</faultstring>
          <detail>
            <e:errorInfo xmlns:e="urn:TclSOAP-ErrorInfo">
              <errorCode>NONE</errorCode>
              <stackTrace>parameter num must be a number
        while executing
    "error "parameter num must be a number""
        (procedure "::urn:tclsoap:Test1::square" line 3)
        invoked from within
    "::urn:tclsoap:Test1::square Hello"
        invoked from within
    "interp eval $xmlinterp [list $xmlns] $argValues"</stackTrace>
            </e:errorInfo>
          </detail>
        </SOAP-ENV:Fault>
      </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
As can be seen from the XML data, if an error is raised by the Tcl implementation of the SOAP method then the SOAP::Domain package includes the stack trace (from the global variable errorLevel) as one of the detail elements. This is very useful for debugging such procedures. There is a sample service in `samples/tclhttpd-sample.tcl` and also a rather complete example implementing the interoperability test suite in `cgi-bin/soap/soapinterop.tcl`.