Tuesday, May 17, 2016

How to avoid issue in default APIs in WSO2 API Manager 1.10

In API Manager 1.10 you may see issue in mapping resources when you create another version and make it as default version. In this post lets see how we can overcome that issue.

Lets say we have resource with a path parameter like this.
 /resource/{resourceId}

Then we will create another API version and make it as default.
As you can see from the xml generated in synapse config, corresponding to the API, the resource is created correctly in admin--resource_v1.0.xml

<resource methods="GET" uri-template="/resource/{resourceId} " faultSequence="fault">

But if you checked newly created default version then you will see following.

<resource methods="GET"
             uri-template="$util.escapeXml($resource.getUriTemplate())"
             faultSequence="fault">

Therefore, we cannot call the resource of the API via gateway with the APIs default version.
Assume we have API named testAPI and we have 3 versions named 1.0.0, 2.0.0 and 3.0.0.
By defining default API what we do is just create a proxy for default version. Then we will create default proxy which can accept any url pattern and deploy it.
For that we recommend you to use /* pattern. It will only mediate requests to correct version. Lets think default version is 2.0.0 then default version API
will forward request to that version. So you can have all your resources in version 2.0.0 and it will be processed there. And you can have any complex url pattern there.

So for default API having resource definition which match to any request is sufficient. Here is the configuration to match it.

  <resource methods="POST PATCH GET DELETE HEAD PUT"
             url-mapping="/*"
             faultSequence="fault">

To confirm this you can see content of default API. There you will see it is pointed to actual API with given version. So All your resources will be there in versioned API as it is.

Here i have listed complete velocity template file for default API.
Please copy it and replace wso2am-1.10.0/repository/resources/api_templates/default_api_template.xml file.

<api xmlns="http://ws.apache.org/ns/synapse"  name="$!apiName" context="$!apiContext" transports="$!transport">
   <resource methods="POST PATCH GET DELETE HEAD PUT"
             uri-template="/*"
             faultSequence="fault">
    <inSequence>
        <property name="isDefault" expression="$trp:WSO2_AM_API_DEFAULT_VERSION"/>
        <filter source="$ctx:isDefault" regex="true">
            <then>
                <log level="custom">
                    <property name="STATUS" value="Faulty invoking through default API.Dropping message to avoid recursion.."/>
                </log>
                <payloadFactory media-type="xml">
                    <format>
                        <am:fault xmlns:am="http://wso2.org/apimanager">
                            <am:code>500</am:code>
                            <am:type>Status report</am:type>
                            <am:message>Internal Server Error</am:message>
                            <am:description>Faulty invoking through default API</am:description>
                        </am:fault>
                    </format>
                    <args/>
                </payloadFactory>
                <property name="HTTP_SC" value="500" scope="axis2"/>
                <property name="RESPONSE" value="true"/>
                <header name="To" action="remove"/>
                <property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
                <property name="ContentType" scope="axis2" action="remove"/>
                <property name="Authorization" scope="transport" action="remove"/>
                <property name="Host" scope="transport" action="remove"/>
                <property name="Accept" scope="transport" action="remove"/>
                <send/>
            </then>
            <else>
                <header name="WSO2_AM_API_DEFAULT_VERSION" scope="transport" value="true"/>
                #if( $transport == "https" )
                <property name="uri.var.portnum" expression="get-property('https.nio.port')"/>
                #else
                <property name="uri.var.portnum" expression="get-property('http.nio.port')"/>
                #end

            <send>
                <endpoint>
                #if( $transport == "https" )
                <http uri-template="https://localhost:{uri.var.portnum}/$!{fwdApiContext}">
                #else
                <http uri-template="http://localhost:{uri.var.portnum}/$!{fwdApiContext}">
                #end
                        <timeout>
                            <duration>60000</duration>
                            <responseAction>fault</responseAction>
                        </timeout>
                        <suspendOnFailure>
                             <progressionFactor>1.0</progressionFactor>
                        </suspendOnFailure>
                        <markForSuspension>
                            <retriesBeforeSuspension>0</retriesBeforeSuspension>
                            <retryDelay>0</retryDelay>
                        </markForSuspension>
                    </http>
                </endpoint>
            </send>
            </else>
        </filter>
        </inSequence>
        <outSequence>
        <send/>
        </outSequence>
    </resource>
        <handlers>
            <handler class="org.wso2.carbon.apimgt.gateway.handlers.common.SynapsePropertiesHandler"/>
        </handlers>
</api>


No comments:

Post a Comment