Converting SOAP and WSDL into REST APIs

Even if most of new APIs today are built around REST, there are still already existing, production applications and systems that expose their APIs using SOAP and WSDL only - in today's article we are integrating with a SOAP service in order to expose it as a REST interface to external applications.

WSDL

WSDL is the language which describes how to invoke SOAP-based applications, using what input, under what address and what output to expect. In the article, we are using a public endpoint whose WSDL you can download here.

Once downloaded, import the WSDL into a tool such as Enterprise Architect or Eclipse to browse its contents. You can also import it to SoapUI to invoke the same service that we are going to access from Zato and Python later on.

Zato Dashboard

The first step is to create a new outgoing SOAP connection in Zato web-admin - simply fill out the form, pointing it to the location of the WSDL resource that contains the description of the remote endpoint.

Once this is done, you will notice a series of entries in the Zato server log, confirming that a queue of connections to the SOAP endpoint has been created successfully.

Python code

We can now author the code needed for the transformation of SOAP into JSON - for simplicity, we are invoking only one specific SOAP service here (LanguageISOCode) but in a full integration project, it would be easy to automate the whole process and have a single transformation service, translating JSON calls into SOAP and the other way around.

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class SOAPTransformer(Service):
    name = 'api.soap.transformer'

    class SimpleIO:
        input = 'lang_name'
        output = 'lang_code'
        response_elem = None

    def handle(self):

        # Name of the SOAP connection pool to use
        conn_name = 'My SOAP Endpoint'

        # Obtain a client from the queue ..
        with self.outgoing.soap.get(conn_name).conn.client() as client:

            # .. prepare input data ..
            lang_name = self.request.input.lang_name

            # .. invoke the SOAP service ..
            lang_code = client.service.LanguageISOCode(lang_name)

            # .. log the result received ..
            self.logger.info('SOAP response: `%s`', lang_code)

            # .. and return the result to our caller.
            self.response.payload.lang_code = lang_code

API channel

After deploying the service above, we can create a REST API channel for it.

Invoking the REST endpoint

Now, it is possible to invoke the REST endpoint - let's use curl to do just that:

WSDL reloading

We are almost done but there is still one point to keep in mind - when a WSDL changes, e.g. when a SOAP endpoint's service modifies its input or output, you need to reload the WSDL in Zato so as to load in the newest updates.

You can do it in web-admin too - go to Connections -> SOAP and click Reload WSDL, as below:

Now we are really through although we could very well go further. For instance, we can add multiple REST channels, handle multiple SOAP backend endpoints or turn WSDL-based services into OpenAPI-based ones. These are all valid subjects but they are left for future articles.