How to return a WSDL through Edge

Do you need to use Edge as a proxy for some legacy SOAP services? Do you want the consumer to retrieve the WSDL from Edge? This article goes through a couple of different options for making a WSDL available through Edge.

First you want to setup a conditional flow for the retrieval of the WSDL. See below for a sample.

(proxy.pathsuffix MatchesPath "/") and (request.verb = "GET") and (request.querystring = "wsdl")

Now you have some options for what to do with your conditional flow.

Option 1

This option is used when you want to have Edge host a static WSDL. In this case Edge will simply return the content you provide.

For this we will use an Assign Message policy to set the WSDL as the payload. Generally a WSDL has an endpoint location. Instead of hardcoding the host DNS you can use the variable “request.header.host” to dynamically populate the location host. Below is a sample policy.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="AssignMessage.returnWsdl">
    <DisplayName>AssignMessage.returnWsdl</DisplayName>
    <Properties/>
    <Set>
        <Payload contentType="text/xml" variablePrefix="@" variableSuffix="#">
            <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.examples.com/wsdl/HelloService.wsdl" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="HelloService" targetNamespace="http://www.examples.com/wsdl/HelloService.wsdl">
                <message name="SayHelloRequest">
                    <part name="firstName" type="xsd:string"/>
                </message>
                <message name="SayHelloResponse">
                    <part name="greeting" type="xsd:string"/>
                </message>
                <portType name="Hello_PortType">
                    <operation name="sayHello">
                        <input message="tns:SayHelloRequest"/>
                        <output message="tns:SayHelloResponse"/>
                    </operation>
                </portType>
                <binding name="Hello_Binding" type="tns:Hello_PortType">
                    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
                    <operation name="sayHello">
                        <soap:operation soapAction="sayHello"/>
                        <input>
                            <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:examples:helloservice" use="encoded"/>
                        </input>
                        <output>
                            <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:examples:helloservice" use="encoded"/>
                        </output>
                    </operation>
                </binding>
                <service name="Hello_Service">
                    <documentation>WSDL File for HelloService</documentation>
                    <port binding="tns:Hello_Binding" name="Hello_Port">
                        <soap:address location="http://@request.header.host#/SayHello/"/>
                    </port>
                </service>
            </definitions>
        </Payload>
        <StatusCode>200</StatusCode>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>

You will also want to ensure you have a Route Rule setup so that this WSDL request is not routed to a target.

<RouteRule name="noTarget">
        <Condition>(proxy.pathsuffix MatchesPath "/") and (request.verb = "GET") and (request.querystring = "wsdl")</Condition>
</RouteRule>
 

Option 1a

Instead of using an Assign Message policy, you can use a Raise Fault policy to set and return the payload. If you use the SOAP wizard, this is how the system auto generates a WSDL response policy. The advantage is that it immediately stops processing and you don’t have to worry about making sure you have a Route Rule. There are, however, some disadvantages with this approach.

  • You may need to account for this in your fault rules (depending on how you are handling faults)
  • A request for the WSDL may show as an error in your analytics
  • It could be a bit confusing since this isn’t really an error condition.

Option 2

Use this option when Edge is acting as a passthrough proxy for an existing service that is already hosting its own WSDL. In this option we simply pass the request along to the target to retrieve the WSDL. Since that WSDL will have an endpoint location we need to replace that value with the correct location of the Edge proxy. This can be accomplished with an XSL Transform policy.

Again you will likely want to use the “request.header.host” variable to dynamically assign the host. You need to set this up in you XSL Transform policy as a parameter. Below is a sample policy and XSLT.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<XSL async="false" continueOnError="false" enabled="true" name="XslTransform.replaceEndpointURL">
    <DisplayName>XslTransform.replaceEndpointURL</DisplayName>
    <Properties/>
    <Source>response</Source>
    <ResourceURL>xsl://XslTransform.replaceEndpointURL.xsl</ResourceURL>
    <Parameters ignoreUnresolvedVariables="false">
        <Parameter name="location" ref="soapEndpointLocation"/>
    </Parameters>
    <OutputVariable/>
</XSL>    
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    
    <xsl:param name="location" select="''"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="@location">
        <xsl:attribute name="location">
            <xsl:copy-of select="$location"/>
        </xsl:attribute>
    </xsl:template>

</xsl:stylesheet>

As you can see it is pretty straightforward to have Edge return a WSDL to the consumer. Please feel free to comment if you have any suggestions or questions.

Comments
mitchellarends
Bronze 5
Bronze 5

Are these still the best options for returning a WSDL from Apigee directly. I was hoping to utilize the WSDL/XSD resources that can be included within the proxy but don't see that reference as an option in this article or any where else within the community.

Version history
Last update:
‎03-22-2017 10:16 AM
Updated by: