SOAP 1.6 Package for Tcl 8.3

Tcl SOAP Client Utility Packages

Contents

  1. Introduction to TclSOAP
  2. SOAP Package Commands
  3. JSON-RPC Package Commands
  4. CGI Server Package
  5. TclHTTPD SOAP Server Utilities
  6. TclHTTPD XML-RPC Server Utilities
  7. Download Information
  8. TclDOM Packages for TclSOAP
  9. TclSOAP over SSL

Introduction

I have been testing out using SOAP from Tcl and have come up with the following package to provide Tcl commands for SOAP remote procedure calls. The following code demonstrates the ease of use for simple RPC calls. This is a work in progress and some parts need more work. In particular the transport layer needs to be able to be configured to cope with proxy HTTP servers and authenticating proxys and the like. Still it may be usefull as-is.

This example connects the Tcl procedure getTemp to the remote method hosted by XMethods. In all these examples Tcl commands are prefixed with the % character that is my prompt under tclsh. Results are printed without the preceeding prompt character.

% package require SOAP
1.6
% SOAP::create getTemp \
    -uri "urn:xmethods-Temperature" \
    -proxy "http://services.xmethods.net/soap/servlet/rpcrouter" \
    -params { "zipcode" "string" }
::getTemp
% getTemp 90810
41.2
We bring in the package and then define the method. The configuration requires a URI for the XML namespace of the SOAP method and a URL for the service. The params configure option allows the Tcl procedure to do simple parameter checking without passing duff packets over the network.

Another example, this time using the extremely clever SOAP::Lite Perl package as a server, a Celcius to Fahrenheit convertor. We shall test it using that peculiar temperature -40. This time I want the Tcl procedure to be called C2F.

% package require SOAP
1.6
% SOAP::create C2F \
    -uri "http://www.soaplite.com/Temperatures" \
    -proxy "http://services.soaplite.com/temper.cgi" \
    -params { "temp" "float"}\
    -name c2f
::C2F
% C2F -40.0
-40
%

It will be possible to use different transport protocols to transfer the SOAP packets. At this time only HTTP is supported. You may need to configure the transport subsystem so the SOAP::configure command has a -transport option. For example, at work I live behind a Microsoft NT firewalling proxy web server. So I need to tell the SOAP transport about the proxy. This is an authenticating proxy, so I have to add a header to all HTTP requests using the Proxy-Authorization HTTP field. Here's how I set up my system and then create a command for the SOAP::Lite languages method.

% package require SOAP
1.6
% SOAP::configure -transport http -proxy proxyhost:8080 \
    -headers { "Proxy-Authorization" "Basic dXNlcm5hbWUgOiBwYXNzd29yZA==" }
% SOAP::create languages \
    -uri "http://www.soaplite.com/Demo" \
    -proxy "http://services.soaplite.com/hibye.cgi" \
    -params {}
::languages
% languages
Perl sh C
%

To setup a method to use a different transport there is a -transport option for the method configure command. This should be set to the name of a procedure that will be called with the URL of the SOAP service and the XML data of the SOAP request. It should return the reply packet or error. For example, I have a dummy transport procedure that prints the SOAP request and doesn't send it anywhere. To see what is being generated for a method:

# A dummy SOAP transport procedure to examine the SOAP requests generated.

proc SOAP::Transport::print::print {procVarName url soap} {
    puts "$soap"
}

% SOAP::configure languages -transport SOAP::Transport::print::print
::languages
% languages
<?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/"
    SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
   <ns:languages xmlns:ns="http://www.soaplite.com/Demo" />
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
%
For debugging purposes it can be useful to see the XML that was generated for the SOAP method request at each end. The SOAP::dump command will return the XML for the last transaction using HTTP for a named method.

Using Complex Variable Types

The SOAP protocol specifies a number of variable types in the default encoding style. Most of these are simply mapped into Tcl however the Array and Struct types create a special problem for Tcl users. Given a string such as "The cat sat on the mat" there is no way in Tcl to determine if this is a string of 6 words, a list with 6 elements or the list representation of a three element array. In SOAP terms, these would be a string, an array of strings, or a struct. To properly implement SOAP clients we must provide a method by which the SOAP framework can determine what the parameters should be mapped into. This is achieved by the -params configuration option and the rpcvar package.

The -params option is used the specify both the number of parameters, their names and their types. In SOAP, the names of the parameters is supposed to be more important than their positions. So:

SOAP::create a -params {num double} Parameter num is a double
SOAP::create a -params {num dateTime} Parameter num is a SOAP dateTime date.
SOAP::create a -params {nums int()} nums is an array of integers
SOAP::create a -params {dates dateTime()} dates is an array of SOAP dateTime values
SOAP::create a -params {anArray array} anArray is an array of mixed types.
The final version in an untyped array. This can also be specified as ur-type() or any(). In the SOAP 1.1 specification these arrays are set to ur-type[n]

Structs can be handled in a similar fashion. The simplest case of a structure of simple guessable types can be handled by specifying a type of struct. In this case the parameter is expected to be a list of name-value pairs. For more complex types, particularly structs containing structs we need to define a new type. This is done using the typedef procedure from the rpcvar package.

package require rpcvar
namespace import -force rpcvar::typedef

typedef {
   intValue    int
   floatValue  float
   stringValue string
} simpleStruct

SOAP::create a -params {myStruct simpleStruct}

a {intValue 2 stringValue "Hello, World!" floatValue 2.5}

An example using a nested struct type can be found in the samples/soapinterop.tcl file shipped with TclSOAP.


Methods

SOAP::create methodName ?option value ...?

Create a Tcl binding for a remote procedure call using SOAP. See configure for the permitted options.

SOAP::configure -transport protocol ?option value ...?

Used for global configuration of the available transports. The options passed in to this command are dependent on the transport mchanism. The only transports currently available

The HTTP transport may require a proxy server and possible other headers to be included. This is where to add this information. For example, to pass an authenticating proxy server I need to provide the name of the server and a Proxy-Authorize HTTP header using the Trf package to provide the base64 encoding procedure.

SOAP::configure -transport http -proxy wwwproxy:8080 \
       -headers { "Proxy-Authorize" "Basic [base64 -enc user:pass]" }
SOAP::configure methodName ?option value ...?

Sets various metadata and attributes of a specific RPC method through the options listed below.

-uri URI
The URI for the XML namespace in which this method has been defined.
-proxy URL
Specify the URL of the server providing the implementation of this method.
-params list
Configure the parameters required for this method. list should be a list of pairs consisting of the parameter name and the parameter type. The Tcl procedure will check the number of parameters when constructing the SOAP request. e.g.:
SOAP::configure getTemp -params { "zipcode" "string" }
SOAP::configure c2f -params { "temperature" "float" }
SOAP::configure hi -params {}

-transport protocolProc
Select the transport protocol used for this method. protocolProc should be a Tcl command procedure that takes the URL of the SOAP server and the SOAP XML data to be sent. This procedure will send the request and receive the answer.
-name methodName
By default a Tcl command is created in the current namespace with the same name as the SOAP method. If the Tcl procedure is created with a different name then the -name configuration option must be used to set the SOAP method name explicitly.
-action SOAPActionValue
The SOAP 1.1 specification requires SOAP POST requests to have an HTTP SOAPAction header. This may have an empty value if not required (which is the default) or it may be required to be set to a specific value to pass though firewalls.
-wrapProc procedureName
Set the procedure used to wrap up the method parameters for transport to the server. This procedure takes the SOAP methodName followed by all the parameters required for the method call and returns the generated XML data for the RPC call. By default for SOAP requests this is set to SOAP::soap_request and for XML-RPC methods to SOAP::xmlrpc_request. This option is only likely to be used if you are implementing a new RPC protocol.
-replyProc procedureName
A hook procedure can be defined to be called once the response packet has been received but before the XML is parsed. Provided the server returned an HTTP 200 response then this procedure is guarunteed to be called even if the reply contains an error response. The procedure is called with two parameters, the first being the SOAP method name and the second being the XML text of the reply. The hook procedure should return the new XML text suitable for processing by the -parseProc procedure. For example:
proc my_reply_hook { methodName xml } {
   puts "$xml"
   return $xml
}
-parseProc procedureName
Specify the procedure used to parse the XML of the reply and to extract the result value. The default depends upon the setting of the -xmlrpc configuration option and is either SOAP::parse_soap_response or SOAP::parse_xmlrpc_response. The procedure takes two parameters as for the -replyProc option but should return the result value from the XML packet.
-postProc procedureName
An optional hook procedure may be specified here that will be called once the result value has been obtained from the XML packet. This procedure will take two parameters, the first is the SOAP method name and the second the result value extracted from the XML. The procedure should return the new result value. By default no procedure is defined.
-command callback
Provide support for asynchronous methods. This option causes the SOAP method invocation to return immediately and the callback procedure is called once the round trip finally completes. The procedure will be called with an additional argument that is the data returned by the remote method. The callback procedure must exist before the SOAP method is configured as the procedure name is namespace qualified during configuration.
   proc gotInfo {window data} { ... }
   SOAP::configure getInfo -command {gotInfo .frame1.edit} ...

SOAP::cget methodName option

Retrieve a configuration value from the method. The optionName should be one of those listed for configure. There is one additional read-only value to be obtained:

http
retrieve the handle for the last HTTP request. This is only set if the transport in use is HTTP. You can examine the HTTP data using procedures from the http package. i.e.:
puts "[::http::data [SOAP::cget getTemp http]]"
or
set r [::http::code [SOAP::cget getTemp http]]


SOAP::dump option methodName

Returns information about the last HTTP transaction.

-reply
returns the XML text of the servers reply
-request
returns the XML text that was sent to the server
-meta
returns the HTTP protocol meta information


SOAP::invoke methodName methodParameters

Make a SOAP call to the configured server. This is not expected to be called by a user but is called by the Tcl command procedure for this SOAP method.

SOAP::proxyconfig

This command presents a dialog box used to configure the SOAP package to work with a proxy server. The fields are used to call SOAP::configure -transport http with the relevant options. The first entry field takes the name and port of the proxy server (eg: webproxy:8080) and the second two fields are used to configure a Basic Authentication HTTP header to allow operation with an authenticating proxy. (such as a Windows NT IIS server).




JSON-RPC Commands

The JSONRPC package provides support for the lightweight RPC protocol defined in the JSON-RPC 1.0 and JSON-RPC 2.0 draft specifications. Currently, the package implements only client side interfaces.

The simple example below shows a remote call to a echo service method hosted at jsolait.net.

% package require JSONRPC
0.1.0
% JSONRPC::create echo -proxy "http://jsolait.net/services/test.jsonrpc" -params { val string }
::echo
% echo "This is a test"
This is a test

The JSONRPC package makes use of the JSON package from tcllib which in turn uses the dict Tcl data type and therefore requires either Tcl 8.5 or the backported dict package for earlier Tcl versions.

The JSONRPC package usage follows the same idiom as the SOAP package. The sample code and examples described there will work with the JSONRPC package. Moreover, the commands defined by the package are almost identical to the SOAP commands. Only the differences are described in the command descriptions below.

JSONRPC::create methodName ?option value ...?

Create a Tcl binding for a remote procedure call using JSON-RPC. See configure for the permitted options.

JSONRPC::configure -transport protocol ?option value ...?

Used for global configuration of the available transports. See SOAP::configure -transport for details.

JSONRPC::configure methodName ?option value ...?

Sets various metadata and attributes of a specific RPC method. Refer to SOAP::configure for a description of the options with the following differences. The options -action and -xmlrpc are irrelevant for JSON-RPC and should not be specified. The following options are new or have different semantics.

-namedparams boolean

If false (default), parameters are sent in the RPC call by position. If specified as true, the parameters are passed by name. JSON-RPC 1.x servers and even many 2.0 servers do not support parameters passed by name.

-version VERSION

The JSON-RPC protocol version to be used. Should be either 1.0 (default) or 2.0 although this not enforced. Any version specification matching 1.* results in JSON-RPC 1.0 data formats. Any other results in JSON-RPC 2.0 data formats.

-params list

This option has the same form and function as the SOAP::configure METHOD -params option except that the only types supported are boolean, int or integer, float, double, string, struct, array and any. The any type can be specified when an array has mixed type elements or when a struct member may hold data of multiple types.

JSONRPC::cget methodName option

Retrieve a configuration value from the method. Refer to SOAP::cget for details.

JSONRPC::dump option methodName

Retrieve information about the last http transaction. Refer to SOAP::dump for details.


Download

The package can be downloaded from the SourceForge project site . This file should be unpacked somewhere handy and you should set your TCLLIBPATH environment variable to suit. For windows users, you may as well unpack it to X:\Program Files\Tcl\lib\

You can also obtain the source via anonymous CVS or browse the CVS repository. You might also find recent news and update information on the TclSOAP project page. This is also the place to report bugs, submit patches and discuss any issues.



$Id: TclSOAP.html,v 1.25 2008/07/06 03:15:09 apnadkarni Exp $