| ActiveTcl User Guide |

| # TclSOAP CGI Server Package |
## Introduction The `SOAP::CGI` package allows you to provide SOAP web services from Tcl scripts via the CGI script capabilities of your web server. This document describes the use of this package with the Apache httpd server but the package should be applicable to any other server supporting the Common Gateway Interface. The package provides a fairly comprehensive framework to deal with hiding the details of the web service protocols. The Tcl scripts implementing the service need to know nothing of XML nor the RPC protocol in use. Errors are returned via the normal Tcl error mechanism. The only special feature needed is variable type hinting. It is not possible to distinguish between a string with whitespace and a list in Tcl, so the `rpcvar` package is used to provide the additional type information when required. ## Installation Installation really only requires placing a script into the http servers cgi-bin directory and writing some service implementations. A generic script is provided as `cgi-bin/rpc` with some example services in `cgi-bin/soap/`. The package has four variables to configure so that it can find the service implementations:
`package require SOAP::CGI set SOAP::CGI::soapdir "../method-scripts" set SOAP::CGI::soapmapfile "soapmap.dat" set SOAP::CGI::xmlrpcdir "../method-scripts" set SOAP::CGI::xmlrpcmapfile "xmlrpcmap.dat" set SOAP::CGI::logfile "../logs/rpc.log" SOAP::CGI::main`
The SOAP and XML-RPC implementations can be the same, as above, or placed into separate directories. The log file is optional (unset the variable to disable logs) and will need to be writable by the httpd user - this usually means it needs to be world writable. The `soapmap` file is used to identify the implementation script file from the SOAPAction header. There is more information in the sample `soapmap.dat` file. The script needs to be able to execute using tcl 8.3 or better and needs to be able to find the TclSOAP package. Bear in mind that the httpd process will not run with your environment (unless you are working on Windows). The supplied script shows how you can set the location of the package, should you need to. If you are using the Windows Apache server then you can't set the environment before `exec`ing tclsh so you need to manipulate the `auto_path` variable from within the CGI script instead. ## Writing Service Implementations Upon receipt of an HTTP POST the CGI framework examines the data and decides which RPC protocol should handle the request. The handlers then retrieve the method name from the request and look for a file with this name in the configured directory. This is sourced and then evaluated with the arguments obtained from the POST data. For example, the implementation for the `square` service will be the file `../method-scripts/square` with the following code:
    proc square {num} {
        return [expr $num * $num]
    }
Given the configuration shown above, this implementation will be used for both SOAP and XML-RPC requests to the `square` service. It is necessary to identify the commands that are webservices to prevent clients from running arbitrary Tcl commands. This is done by the use of the `SOAP::export` or the corresponding `XMLRPC::export` commands. This means that the actual implementation for the square webservice would be:
    package require SOAP
    package require XMLRPC

    SOAP::export square
    XMLRPC export square

    proc square {num} {
        return [expr $num * $num]
    }
For more complex types such as structs, the reply will need to be an `rpcvar` so that the RPC handler can package the result correctly. So the implementation of the `platform` service which returns a struct containing the `::tcl_platform` variable information is as follows
    package require rpcvar
    package require SOAP
    SOAP::export platform

    proc platform {} {
        return [rpcvar::rpcvar struct ::tcl_platform]
    }
Structs are passed to the implementing procedure as a list of name value pairs suitable for use with `array set ...`, arrays are passed in as Tcl lists and everything else is passed in as a string. If the result type cannot be guessed then you should return a typed variable otherwise it will be assumed to be a string. The only types that can be guessed are integer, double and boolean (if expressed with `true` or `false`). ## Providing Type Information rpcvar to be done ## Further Information Look in the `cgi-bin/soap` subdirectory in the TclSOAP distribution for some examples of service implementations. There is an implementation of the UserLand SOAP interoperability suite that is used to ensure the package conforms to this standard. These illustrate the use of arrays and structs fairly comprehensively. The client code for the validator suite is in `samples/validator.tcl`. To test a server implementation, source this script and run `validate_soap url`. This will run the test suite against the server implementation at the provided URL. A similar client implementation of the XMethods Interoperability Lab test suite is in `soapinterop.tcl`. To use, source this file and execute `soapinterop::validate url`.