Transform Existing SOAP Based Web Service To REST Based API Using Azure API Management

This article will explain how to transform existing SOAP based Web Services to REST based API , using Azure API Management.

Prerequisites

  • Azure account
  • Azure API Management resource.

Step 1

Login to your Azure account.

Step 2

Click + icon to add new resource and search for API Management.

Azure 

Step 3

Click API Management icon, which will take you to API Management creation process.

Step 4

Enter the appropriate details in the below form and click Create button. It will create Azure API Management interface through which you can manage your API. Now, we will use this newly created API Management to transform the SOAP backend to REST API.

Step 5

Go to the newly created API Management resource screen and click Publisher portal.

Step 6

In the Publisher portal, click Import API.

Azure

Step 7

Select WSDL as Specification Format and enter SOAP link in Specification Document URL and enter the appropriate details, as shown below and click Save. 

Note

I have used an open source SOAP Service for the explanation.

Azure

Step 8

If the WSDL has multiple end points, the screen given below will appear. Among multiple items, we are able to choose only one. Choose "OrdersAPI::basic and click Select button.
Azure
Now, you will see the screen given below with SOAP based Web Service Orders API, which has been imported to Azure API Management , as shown below.

Azure 

Now API Management will transform SOAP backend to REST API.

During the import process, Azure API Management will generate the special policies to the inbound transform from JSON to a SOAP and the same thing will happen on the outbound flow.

Step 9

Click Operation to view the API definition and you can see in the screen given below that Orders API are now transformed to REST API structure. The structure of Orders Service shows the image given below. We will use this structure to discuss about the further transform process.

Azure

Step 10

Click GetOpenOrders and you can see it is having REST API structure with the http verbs. Here, the request is provided to REST based GetOrders. In the background, the request transfers to Rewrite URL template, which holds SOAP Service reference.

Azure

Step 11

Click Policies to view in more detail about the background process.

Under API dropdown, select OrdersAPI, Operation as GetOrders and click Configure Policy.

Azure

Proceed with the code, as shown below.

  1. <policies>  
  2.     <inbound>  
  3.         <base />  
  4.         <rewrite-uri template="/FazioService.svc" copy-unmatched-params="false" />  
  5.         <set-header name="SOAPAction" exists-action="override">  
  6.             <value>"http://tempuri.org/IFazioService/GetOrder"</value>  
  7.         </set-header>  
  8.         <set-body template="liquid">  
  9.             <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://tempuri.org/">  
  10.                 <soap:Body>  
  11.                     <GetOrder>  
  12.                         <orderId>{{body.getOrder.orderId}}</orderId>  
  13.                     </GetOrder>  
  14.                 </soap:Body>  
  15.             </soap:Envelope>  
  16.         </set-body>  
  17.         <set-header name="Content-Type" exists-action="override">  
  18.             <value>text/xml</value>  
  19.         </set-header>  
  20.     </inbound>  
  21.     <backend>  
  22.         <base />  
  23.     </backend>  
  24.     <outbound>  
  25.         <base />  
  26.         <choose>  
  27.             <when condition="@(context.Response.StatusCode < 400)">  
  28.                 <set-body template="liquid">  
  29.                                                     {  
  30.   "getOrderResponse" :   
  31.   {  
  32.     "getOrderResult" :   
  33.     {  
  34.       "customer_id" : {{body.envelope.body.GetOrderResponse.GetOrderResult.customer_id}},  
  35.       "line_items" :   
  36.       [  
  37.         {% JSONArrayFor item in body.envelope.body.GetOrderResponse.GetOrderResult.line_items-%}  
  38. {{item}}  
  39.         {% endJSONArrayFor -%}  
  40.       ]  
  41. ,  
  42.       "order_header_data" :   
  43.       {  
  44.         "bar" : {{body.envelope.body.GetOrderResponse.GetOrderResult.order_header_data.Bar}},  
  45.         "foo" : "{{body.envelope.body.GetOrderResponse.GetOrderResult.order_header_data.Foo}}"  
  46.       },  
  47.       "order_id" : {{body.envelope.body.GetOrderResponse.GetOrderResult.order_id}},  
  48.       "shipping_address" :   
  49.       {  
  50.         "address1" : "{{body.envelope.body.GetOrderResponse.GetOrderResult.shipping_address.Address1}}",  
  51.         "address2" : "{{body.envelope.body.GetOrderResponse.GetOrderResult.shipping_address.Address2}}",  
  52.         "city" : "{{body.envelope.body.GetOrderResponse.GetOrderResult.shipping_address.City}}",  
  53.         "country" : "{{body.envelope.body.GetOrderResponse.GetOrderResult.shipping_address.Country}}",  
  54.         "stateCounty" : "{{body.envelope.body.GetOrderResponse.GetOrderResult.shipping_address.StateCounty}}",  
  55.         "zipPostcode" : "{{body.envelope.body.GetOrderResponse.GetOrderResult.shipping_address.ZipPostcode}}"  
  56.       }  
  57.     }  
  58.   }  
  59. }  
  60.   
  61.                                         </set-body>  
  62.             </when>  
  63.             <otherwise>  
  64.                 <!-- Error response as per https://github.com/Microsoft/api-guidelines/blob/master/Guidelines.md#7102-error-condition-responses  -->  
  65.                 <set-body template="liquid">  
  66.                                         {  
  67.                                         "error": {  
  68.                                             "code": "{{body.envelope.body.fault.faultcode}}",  
  69.                                               "message": "{{body.envelope.body.fault.faultstring}}"  
  70.                                               }  
  71.                                         }  
  72.                                     </set-body>  
  73.             </otherwise>  
  74.         </choose>  
  75.         <set-header name="Content-Type" exists-action="override">  
  76.             <value>application/json</value>  
  77.         </set-header>  
  78.     </outbound>  
  79. </policies>   
Look at <set-body> tag, which refers to the liquid template. It holds SOAP structure and transforms it into REST response.

Azure

In the screen given below, you can see JSON response template, which has been rendered as JSON from SOAP body XML. It ensures that REST API returns JSON response to your frontend.


Azure

Proceed with the code given below.

  1. <set-body template="liquid">    
  2.                                                     {    
  3.   "getOrderResponse" :     
  4.   {    
  5.     "getOrderResult" :     
  6.     {    
  7.       "customer_id" : {{body.envelope.body.GetOrderResponse.GetOrderResult.customer_id}},    
  8.       "line_items" :     
  9.       [    
  10.         {% JSONArrayFor item in body.envelope.body.GetOrderResponse.GetOrderResult.line_items-%}    
  11. {{item}}    
  12.         {% endJSONArrayFor -%}    
  13.       ]    
  14. ,    
  15.       "order_header_data" :     
  16.       {    
  17.         "bar" : {{body.envelope.body.GetOrderResponse.GetOrderResult.order_header_data.Bar}},    
  18.         "foo" : "{{body.envelope.body.GetOrderResponse.GetOrderResult.order_header_data.Foo}}"    
  19.       },    
  20.       "order_id" : {{body.envelope.body.GetOrderResponse.GetOrderResult.order_id}},    
  21.       "shipping_address" :     
  22.       {    
  23.         "address1" : "{{body.envelope.body.GetOrderResponse.GetOrderResult.shipping_address.Address1}}",    
  24.         "address2" : "{{body.envelope.body.GetOrderResponse.GetOrderResult.shipping_address.Address2}}",    
  25.         "city" : "{{body.envelope.body.GetOrderResponse.GetOrderResult.shipping_address.City}}",    
  26.         "country" : "{{body.envelope.body.GetOrderResponse.GetOrderResult.shipping_address.Country}}",    
  27.         "stateCounty" : "{{body.envelope.body.GetOrderResponse.GetOrderResult.shipping_address.StateCounty}}",    
  28.         "zipPostcode" : "{{body.envelope.body.GetOrderResponse.GetOrderResult.shipping_address.ZipPostcode}}"    
  29.       }    
  30.     }    
  31.   }    
  32. }    
  33.     
  34.                                         </set-body>    
You can click the Cancel button now. Let us view REST API behavior in the developer portal.

Step 12

Go to API management overview and click Developer portal.

Azure

Step 13

In the developer portal, go to Orders API. Use the developer console to see a RESTful payload is coming back to you from SOAP API.

Azure

Click GetOpenOrders, hit Try It button and you will be presented with an example request. 

Azure

In the request body JSON, enter the appropriate request JSON message and click Try it.

Azure 

Now, you can see the JSON response below, which has the response message with the response latency details.

Azure

You can also explore the overall execution process under the Trace tab.

Conclusion

As Azure API Management offering is frequently getting loaded with back to back new features, the SOAP to REST transformation feature is a great addition to Azure API Management and this feature is very user friendly. The developer can expose his existing SOAP Service as REST API without much effort.