Saturday, January 2, 2016

WSO2 API Manager Using custom headers via swagger ui

Due to various reasons most of the back end APIs are expecting headers which are not allowed by the default CORS Handler used in WSO2 API Manager. Due to the restrictions by CORS Handler while invoking APIs with custom headers fail if we use the swagger UI. This is due to the OPTION call sent to API gateway from publisher to get the allowed header types (if we are using curl or other api clients this doesn't fail because we don't us the OPTION call in it).

List down below is how to add a custom header on WSO2 API Manager and make it usable via swagger UI.

1. Start creating an API according to [1]
2. Click on EDIT Source in the step 3 provided in the tutorial

add the following swagger file to the swagger file and save

paths:
  /weather:
    post:
      x-auth-type: "Application & Application User"
      x-throttling-tier: Unlimited
      parameters:
        - schema:
            type: object
          description: Request Body
          name: Payload
          required: false
          in: body
        - name: ActionHeader
          description: The Header
          type: string
          required: false
          in: header
        - name: q
          type: string
          required: false
          in: query
        - name: appId
          type: string
          required: false
          in: query
      responses:
        "200": {}
    get:
      x-auth-type: "Application & Application User"
      x-throttling-tier: Unlimited
      parameters:
        - name: ActionHeader
          description: The Header
          type: string
          required: false
          in: header
        - name: q
          type: string
          required: false
          in: query
        - name: appId
          type: string
          required: false
          in: query
      responses:
        "200": {}
swagger: "2.0"
info:
  title: HeaderTutorial
  version: v1


Note that following block adds the ActionHeader as a header parameter to the resource.

        - name: ActionHeader
          description: The custom Header
          type: string
          required: false
          in: header

3. Then continue with the step 5 in tutorial.

4. After successfuly publishing the API you can subscribe to it through API store and invoke the API. When API is invoked you can find that below type of error message is vibile on the swagger console.



5. The above happens because the ActionHeader is not allowed in the CORS Configuration. In order to allow it first stop the running API Manager Instance

6. Open <APIM HOME>/repository/conf/api-manager.xml

7. Add the ActionHeader value to <Access-Control-Allow-Headers> under <CORSConfiguration>tag as follows


After the adding the value the Access-Control-Allow-Headers should like following

<Access-Control-Allow-Headers>authorization,Access-Control-Allow-Origin,Content-Type,SOAPAction,Authorization,ActionHeader</Access-Control-Allow-Headers>

8. Save the file and restart API Manager

9. Invoke the api using the swagger UI you will find the API getting successfully invoked now.

The below video tutorial show the steps of how to achieve this





[1] https://docs.wso2.com/display/AM191/Create+and+Publish+an+API 

Adding a Tenant Specific Custom Handler WSO2 API Manager

Writing a Handler for WSO2 API Manager is pretty straight forward and you can find it in [1]. When it comes to multi tenancy there might be instances that this particular handler should be applied only to a specific tenant or a set of tenants. In doing so we have to edit the /repository/resources/api_templates/velocity_template.xml to include the handler to only a specific tenant. This is the template file used in WSO2 API Manager to create synapse file required to create the api. Here we have to write a simple velocity logic to add the handler only for the specific tenants. If this logic is not added the handler will be applied to all the tenant hence resulting in a performance tradeoff. 

You can add the below logic right after the handlers tag in the velocity_template.xml

        #if ( $apiContext.contains("/abc.com/") )
           <handler class="package.path.to.class" />
        #end

This will add the handler to the abc.com tenant only. You can also extend this to multiple tenant with having a logical OR "||" operator for the contains check.

Just write and save the file and will be added to the template.

[1] https://docs.wso2.com/display/AM191/Writing+Custom+Handlers