The Apigee Dev Portal does not support SOAP/WSDL (Simple Object Access Protocol/Web Service Definition Language) documentation by design. However, Apigee is seeing a number of prospects and customers who have legacy SOAP APIs that they want to onboard onto Apigee Edge quickly. Apigee’s current strategy is to put a REST (Representational State Transfer) facade in front of a SOAP backend as an interim solution. This way customers can take advantage of the out-of-the-box analytics as part of their rationalization exercise to improve and build new RESTful APIs. However, these enterprise clients want to display WSDL documentation in addition to RESTful API documentation. As including comprehensive SOAP/WSDL documentation in the Apigee Dev Portal is not the end goal, this module (Drupal’s equivalent of an “app” or “plugin”) was imagined as an interim solution. It can act as a stand-alone module to be used to quickly get a client ramped up on the Apigee platform without having to do the impossible task of ripping out and rewriting their entire SOAP API “overnight.”
Development of this module serves as an example of how something can be built quickly by borrowing from other of Drupal contributed modules. The codebase we used first started as a standalone form to easily send requests to web services as the sandbox project Webservices Client Tester. It then became absorbed into the Drupal project Web Service Client. Later on, it was customized to focus on testing only SOAP web services. This latest iteration is what we built upon, however, it was not fully baked, loaded with commented code and had some key functionality (sending SOAP requests) that was broken. After significant refactoring, things looked good enough to start building out our requirements.
A WSDL file for SOAP is similar to an OpenAPI spec for REST. It describes a web service/API to developers who want to work with it. The original sandbox Web Services Client Tester module provides an admin UI to import a WSDL. It then stores it as a JSON object inside two tables, operations and parameters. In the Drupal admin, you can view the methods and parameters and view traced SOAP requests. This did not fit our use case as we wanted to create documentation for a developer, not simply create a Drupal admin page for testing.
The best application we could find to convert WSDL files to human readable documentation was WSDL viewer, so this was used as a guide. Our solution was to follow the model of the Apigee Dev Portal SmartDocs by generating nodes for each operation and then rendering the SOAP trace form on each node. By choosing to display each operation on a node, it allows SEO friendly navigation of documentation throughout the Dev Portal and the flexibility to display the operation nodes in views.
Importing the WSDL and generating nodes.
In addition to importing through the UI we needed to create a REST endpoint to import the WSDL for continuous integration (CI/CD), the endpoint is created with hook_menu()and runs the import function that generates the nodes and parses the data. This function can also be called from the Drupal admin by submitting the URL of the WSDL through a form.
For imports via file upload we post.
For imports via URL parameter.
We pass the name parameter In the URL to define a label for the web service as this is defined manually when imported via the Drupal admin UI.
If we are importing by URL we also pass a “url” parameter with the location of the WSDL. If we find no $_POST data for URL, we recognize the WSDL as a file upload, we then use file_get_contents('php://input') to save it to the server and create the service record in the DB.
We check if the WSDL filename exists in our table. If it does not exist we create the service. If it does exist we update the existing service with a new timestamp and user information and then update all existing operation node/
Finally, if we delete the service ID from the Drupal admin all corresponding operation nodes related by ID are deleted.
We added basic auth functionality to the endpoint by copying some code from Basic HTTP Authentication module to the access callback on the menu item. This leverages Drupal’s flood_register_event for extra security, by logging failed attempts to the ‘flood table’/ Admins can view the IP address and timestamp of any failed POST to our endpoint, and a user can also add the Flood Control module to easily view these via the admin UI.
Parsing the WSDL file into Drupal fields had its own set of challenges.
The output of the operation is very important for the developer to know so they clearly see what kind of data they can expect as a return value to their API calls. Parsing the data from the operations was a challenge however because they are not simply stored in an <output> element inside the <operation> element. That’s just not how WSDL files work.
Say we want to parse the output for the operation LatLonListZipCode and store it on a field. We start with the <operation> element where we find GetFlightData,
<wsdl:documentation>Returns basic flight information.</wsdl:documentation>
<wsdl:input message="tns:GetFlightDataHttpPostIn" />
<wsdl:output message="tns:GetFlightDataHttpPostOut" />
We then follow that to the <message> element GetFlightDataHttpPostOut where we need to parse the name and type values.
<wsdl:part name="Userid" type="s:string" />
<wsdl:part name="Password" type="s:string" />
<wsdl:part name="ACID" type="s:string" />
In order to display the data as nested, we have a custom function that loops through the parsed data returning the text inside <li> tags. We then set the form field config to “text area” with input format “full HTML” in Drupal admin.
It’s this kind of unintuitive structure of the WSDL that makes the move to REST and JSON look so very reasonable. This module is a tool in Apigee’s vision towards promoting the move towards a RESTful web, by serving as a stepping stone for companies with SOAP based APIs.
I was fortunate to work with two other great developers Karl and Deb from Achieve who provided me with excellent feedback throughout development. I find the process of being able to demo and show work to a supportive team throughout development as one of the keys to the successful delivery of quality code on time.