SOAP ISAPI extension

# mod_gsoap ISAPI Extension

gsoap is an open source project that can be used to generate Simple Object Access Protocol (SOAP) clients and servers. mod_gsoap allows you to run these services integrated in process inside the Microsoft Internet Information server. It is implemented as an ISAPI extension dll and so can be run together with all other services on IIS.

## Overview

There is an open source project at http://www.cs.fsu.edu/~engelen/soap.html which implements SOAP in C++. Servers created there can be run standalone or as cgi. This is a contribution to get a production quality Web service for MS-Internet Information Server that drives SOAP servers. All the source code and documentation is available for download.

Existing gsoap servers can be compiled without any change in the source code to run inside IIS. There is one dll, mod_gsoap.dll, an Isapi extension that serves SOAP requests. From the query string in the request the extension finds out which server should be used and the appropriate server dll (dynamic link library) is dynamically loaded at runtime, if not already present. This SOAP server creates the response which is sent back to the client by IIS.

To add more servers only the new dlls need to be compiled, the ISAPI interface need not be changed for that, the Web Service not even restarted.

This distribution contains also the standard gsoap calc.h - server to demonstrate operation. The source code of that example was not changed from the standard distribution.

Once your gsoap service works as a standalone application, you only need to recompile it as a dll and copy that dll to your IIS - virtual directory.

In spite of that instructions can be found below for debugging the IIS extension under Windows™ 2000 and XP.

## Requirements

To build the mod_gsoap ISAPI extension for Windows you need the following:

- gsoap 2.3.8 or higher from gsoap
- mod_gsoap_win_0_0_2.zip from http://www.aberger.at/SOAP/mod_gsoap_win_0_0_2.zip

To run mod_gsoap ISAPI extension you need either Windows™ NT 4.0 with Windows™ NT Option Pack 4.0, Windows™ 2000 or Windows XP or higher, where IIS™ is integrated.

## Installation and testing

### Unpack and/or compile the mod_gsoap.dll ISAPI extension

- Unpack the mod_gsoap_win_*.zip package.
- Make sure that gsoap 2.1.8 or higher is unpacked on your computer.
- The package already contains the compiled mod_gsoap.dll, so if you don't want to compile it yourself you can skip the next few lines and continue with installation.
- Open Visual Studio C++ 6.0
- Go to "Tools|Options". Activate the "Directories" Panel.
- Select "Include Files" from the dropdown and add your soapcpp directory (the one where you have unoacked soap 2.18 or higher). This will let the compiler find stdsoap2.H
- Select "Executable Path" and add the same directory also there. This will let Visual Studio find soapcpp2.exe
- Open all4iis.dsw
- Activate the "all4iis" project and build all.

### Installation of mod_gsoap.dll ISAPI extension on your IIS Server

- Add a gsoap folder to your wwwroot directory (e.g. C:\Inetpub\wwwroot\gsoap)
- Open Internet Service Manager from Control Panel->Administrative tools.
- Create in Internet Service Manager a new virtual directory called "gsoap" (details here and also on the Screen Snapshot).
- Copy mod_gsoap.dll and calc.dll to the created gsoap folder (C:\Inetpub\wwwroot\gsoap)
- Start the "World Wide Web Publishing Service"
- Enter in your browser "http://localhost/gsoap/mod_gsoap.dll". This should give a response from the server that explains what the correct url is. If so this proves that mod_gsoap.dll is configured correctly.
- Next enter in your browser "http://localhost/gsoap/mod_gsoap.dll?calc". This should give a response from the server that you should use a POST command, not a GET. This proves that mod_gsoap could load your server dll. So in principle your installation seems to be OK now.
- Check the file .\isapi\samples\calc\calcclnt.c The URL there must corrspond to your installation. Check the line:
  const char server[] = "http://localhost//gsoap/mod_gsoap.dll?calc";
- Open a DOS - command window and change to the directory where calcclnt.exe has been build within the all4iis project. Enter "calcclnt add 3 5".
- Check that the response is: "result=8". If so: Done!
- If not so please read the FAQ.

There is also a dime sample in the code that shows you how to send and receive dime attachments (binary files etc). This sample also shows how to use module initializer and terminators. When the dll is loaded into IIS for the first time the function mod_gsoap_init is called. Here you can initialize database connections or whatever you like. mod_gsoap_terminate is called when the dll is unloaded again. A good place to clean up.

## Compiling your own gsoap - Servers for use with mod_gsoap

- Build and test your standalone gsoap server as documented in gsoap.
- Make sure that your Visual Studio include and executable paths is correct as described above.
- In Visual Studio C++ 6.0 select "File|New". Create a new empty Win32 - Dynamic Link Library.
- Copy stdsoap2.def from the .\isapi\samples\calc example to your project directory and add it to the project. This will ensure that the required functions (soap_init, soap_serve etc) are exported from the dll.
- Compile it
- Copy it to the ...wwwroot/gsoap directory described above.
- Done!

The URL for the new servers is always "http://localhost/gsoap/mod_gsoap.dll?mydll" where mydll is the name of our dll without the .dll extension.

#### Details for creating the virtual root

If you have problems creating the virtual root as descibed above here a short how-to: Open from control panel "Administrative Tools" and then "Internet Services Manager" (under Windows™ NT 4.0 you find it in the Option Pack submenus). Click with the right mouse button on "Default Web Site", then select "New" and "Virtual Directory". Click "Next" and enter as Alias the name you want to give to the url, e.g. "soap", press "Next" again. Then browse for the directory where your dll that you have built in the previous step is, for example "c:\Inetpub\wwwroot\gsoap". Press "Next", then in the access permissions, disable all permissions except "Excute (such as ISAPI applications or CGI)", this must be enabled. Click "Next" and "Finish". For testing it might be a good idea to enable the "Browse" permission and then browse to "http://localhost/gsoap".

### How the url of the request is constructed

The ISAPI SOAP Binding can run together with all other Internet services on your machine on port 80 (or any other, as configured in IIS). It is an extension for IIS. The request your SOAP client must submit is made up of 2 parts. Here is an example:

"http://127.0.0.1/gsoap/mod_gsoap.dll?mySoap"

The part before the question mark '?' is the url for the isapi binding dll. This is evaluated by IIS. In this sample the service is on the same machine as the server. Instead of "127.0.0.1" you can use the DNS address of your server, of course. gsoap is the virtual root created above and mod_gsoap.dll is the generic ISAPI binding from this contribution. The extension mod_gsoap.dll evaluates the part behind the '?', which is in this example mySoap. To this the string ".dll" is appended and the dll is loaded. Due to security reasons only dlls from the same directory are allowed. If you want to do special initialization in your dll you may want to add and export a "DllMain" function, which will be called when the IIS process attaches to your all and before it detaches it. Do not rely on the Thread attach/detach callback, in my experience IIS does not always call DllMain in your dll if these threads were already in the thread pool before your dll was loaded. Use thread local storage instead.

## Development and Debugging

There are a lot to say about debugging of course. Please make sure that your gsoap server works as a standalone server and client before you continue to use it inside IIS.

### IIS Debugging

For Debugging with Win2000 I added two .reg files, that switch debugging of IIS on and off (see Q273639 and related), and a start and stop command in the Makefile to start and stop iis debugging. Make sure that the path to msdev is in the System environment variables ("PATH") of the system account (not only of your own user account, this is not seen by IISAdmin).

If you want to debug, you must set the dll to run in-proccess. Right-click on the gsoap virtual root in internet service manager and set the "Appication Protection" to "Low (IIS Process)". Remove the "Enable Session State" and buffering and Parent Paths. Don't forget to allow the IISAdmin and WWW Service to interact with desktop.

## Makefile

I added some commands to a Windoze "Makefile". To make live easier. See the Makefile yourself, there are commands to start and stop debugging of IIS and cleaning the directory. The very advanced Windoze user can even compile everything without a mouse by running one command. Be sure that msdev.exe and nmake.exe are in your PATH. Then enter from the commandline:

nmake

Such advanced users should also consider to use the linux/unix version mod_gsoap.so, also available on this site. ;-)

Enjoy!

with best regards Christian Aberger

# Frequently asked questions

1. Q: mod_gsoap answers properly in the browser. But then I get the following output:

C:\>calcclnt.exe add 3 5
SOAP FAULT: SOAP-ENV:Client
"End of file or no input"
Detail: http://localhost/gsoap/mod_gsoap.dll?calc
Answer:
Step one: Could you please compile calcclnt.exe with the DEBUG option.
(in Preprocessor Definitions add DEBUG).
Delete all .log files from the current directory if any. Then run
again calcclnt.exe add 3 5
Then you should get 3 files with the extension ".log" in the current
directory. Please read what is in there.

Step two: Make sure that dumpbin.exe is in your PATH (it can be found somewhere in Visual Studio 6.0 binaries).
Open a command shell, change to the directory where mod_gsoap.dll is located (C:\Inetpub\wwwroot\gsoap) and type the following:
dumpbin /exports calc.dll. This output should contain the exported symbols that are listed in the stdsoap2.def file. If you don't find these symbols you propably forgot to add the stdsoap2.def file described here.