Adding interceptors for your APIs using WSO2 API Microgateway
By: Chashika Weerathunga
Tags: Java, Wso2 Apim, Interceptors, Wso2, Http Interceptors

In this article, I will give you a brief introduction about the interceptors and show you how to add interceptors to your APIs using WSO2 API Microgateway.

As API developers in some cases, we need to do the preprocessing of the request or postprocessing of the response before it reaches the backend or client. This is where interceptors come into play.

Interceptors are like gatekeepers when you want to meet the manager in real life. If you haven’t brought the necessary documents, Gatekeeper can reject you before you reach the manager. That's a simple use case for the intercepter in the real world.

Assume that we have implemented a request interceptor. when API consumer invokes the API, it first hits the interceptor and the interceptor can read the request header and the payload and can do whatever preprocessing of the request that the developer has implemented. And if we have a response interceptor, the response first hits to the interceptor before it reaches the client and can do any post-processing it wants.

Why we need interceptors?

Interceptors can perform operations such as validation, exception handling, displaying intermediates results, logging, localization, and many more things.

Interceptors are pluggable components to your application. Assume that the developer has not implemented things like validation, exception handling in their application. If he wants to implement those things in the application, usually he has to redeploy the application which is a costly operation. But by plugging an interceptor, he can do the mentioned tasks easily without redeploying the application.

Okay, now we have an idea about the interceptors. So let's try out how we can add interceptors to our APIs.

Here, I am going to use WSO2 API Microgateway, which is an open-source lightweight gateway distribution to add interceptors. Before implementing an interceptor let’s configure the Microgateway.

Configure WSO2 Microgateway

( If you have already configured WSO2 Microgateway, you can skip these steps)

Step 1- Install prerequisites

First, make sure that you have installed Java JDK 1.8 version to your system and set JAVA_HOME as your environment variable.

Step 2 -Install WSO2 API Microgateway

There are two-components in the WSO2 Microgateway which are Toolkit and Runtime. You have to download both the Toolkit and Runtime based on your operating system.

You can download Toolkit and Runtime from the WSO2 official website and you can find more details about WSO2 API Microgateway in WSO2 API Microgateway Documentation.

Adding APIs to the Microgateway

Go inside the bin folder in the toolkit and you can initialize a project using the following command. (my project name is “petstore” )

./micro-gw init petstore

Then you can see a folder named “petstore” in the current directory.

Then we can add Open API definitions to the petstore > api_definitions folder. Here, I will use a Petstore API definition. But, you are free to use your own APIs. You can find my example definition here, at petstore_basic.yaml. Copy this .yaml file and add it to the petstore > api_definitions folder(.yaml file name can be anything you want. Ex: petstore_basic.yaml). Here you can see the base path is defined as /petstore/v1 (you can define as whatever you want) and the production endpoint defined as http://petstore.swagger.io/v2.

Structure of petstore_basic.yaml

And also this definition includes two resources which are /pet/{petId} and /pet/findByStatus. Here both the resources are exposed by one production endpoint and if you want you can expose different resources via different endpoints as microservices (if you define different endpoints to resources, add the endpoints under the resource>get )

Write java interceptor

After the latest release(3.1.0) onwards we can write interceptors from Java language in WSO2 API Microgateway. In this article, I will write the interceptor using Java language. (If you want to find more details about WSO2 Microgatway intercepters you can find from WSO2 API Microgateway Documentation ).

Microgateway has defined Java interface to write our request and response interceptors. You can see the interface below.

Interceptor interface

We can implement these interface methods to write our interceptors to achieve custom transformation and mediation logic.

Let’s start the implementations…

Step 1- create a maven project

Here I am creating a maven project using IntelliJ IDEA.

I have created a maven project named javaInterceptor. Before writing the interceptor we need to include the Microgateway interceptor dependency for the project.

Step 2- Add dependencies

<dependency>

<groupId>org.wso2.am.microgw</groupId>

<artifactId>mgw-interceptor</artifactId>

<version>3.1.0</version>

</dependency>

Include this dependency to your project pom file.

Dependencies

Step 2- Write interceptor class

Create a Java class(My class name is “SampleInterceptor”) and implement it using the Microgateway Interceptor interface. I will implement the two Interceptor methods which are interceptRequest() and interceptResponse() as below.

package mgw.interceptor;



import org.json.JSONObject;

import org.wso2.micro.gateway.interceptor.Caller;

import org.wso2.micro.gateway.interceptor.Interceptor;

import org.wso2.micro.gateway.interceptor.InterceptorException;

import org.wso2.micro.gateway.interceptor.Request;

import org.wso2.micro.gateway.interceptor.Response;





public class SampleInterceptor implements Interceptor {



public boolean interceptRequest(Caller caller, Request request) {

boolean hasApiKey = request.hasHeader("X-API-KEY");

if (!hasApiKey) {

Response response = new Response();

JSONObject responsePayload = new JSONObject().put("error", "Missing required header");

response.setResponseCode(400);

response.setJsonPayload(responsePayload);

caller.respond(response);

// If we respond from the interceptor it is necessary to set the return value as false.

// Otherwise the usual request flow will continue.

return false;

}

return true;

}

public boolean interceptResponse(Caller caller, Response response) {

// Send a custom json message if the response contains the key "error"

try {

JSONObject responseObject = response.getJsonPayload();

if(responseObject.has("error")){

JSONObject customErrorMessage = new JSONObject().put("error", "Invalid json payload returned");

response.setJsonPayload(customErrorMessage);

}

} catch (InterceptorException e) {

System.out.println("Error while getting the response payload");

}

return true;

}

}

interceptRequest(Caller caller, Request request) My example logic is to validate whether the request header has X-API-KEY. If it doesn’t have that header value, I will create an error response with status code 400 and return back to the client without redirecting it to the backend. interceptResponse(Caller caller, Response response) If the response payload contains the keyerror, I will create a customer error message and sent it to the client

Keep in mind in the logic if you respond from the interceptor, you have to set the return value as false. Otherwise, the normal flow will continue.

Now we are done with writing interceptors. Time to build the project and create the jar file of the project. Execute the following command to build the project(make sure you have installed maven)

mvn clean install

Now inside the project ->target folder you can see the jar file.

Adding the java interceptor to Microgateway

Now its time to add the interceptors to our Microgateway project.

Step 1- Add the interceptor jar file to the project

First, add the generated interceptor jar file to the petstore(initialized Microgateway project) -> lib folder.

Step 2- Add the interceptor extensions

Then let's add the interceptor extension to our OpenAPI definition. My package name is mgw.interceptor and the interceptors’ class name is SampleInterceptor and the java interceptors are specified using the prefix “java:”

You can add the following extension code to the .yaml file.

x-wso2-request-interceptor: java:mgw.interceptor.SampleInterceptor

x-wso2-response-interceptor: java:mgw.interceptor.SampleInterceptor

After adding this you can see the petstore_basic.yaml file like below.

API level

If you want to add interceptors to any specific resource you can add it like below.

Resource level

Now that’s done. It’s time to run Microgateway and try out the interceptors.

Generate runtime artifacts

Again go to the bin directory of the toolkit and execute the below build command and it will generate the runtime artifacts.

./micro-gw build petstore

The output of the terminal shows you the path of the generated artifacts.

artifact path

Now we have finished with the toolkit and let’s move to the gateway runtime.

Run the API Microgateway

Copy the path of the generated petstore.jar file and navigate to the <MGW_HOME>/bin folder and execute the following command to start the Microgateway.

./gateway <path-to-MGW-executable-file>

In my example,

<path-to-MGW-executable-file> = home/chashika/Documents/wso2/releases/wso2am-mic

ro-gw-toolkit-linux-3.1.0/bin/petstore/target/petstore.jar

You have successfully added your API to the Microgateway with java interceptors and started the Microgateway. Now it’s time to try out the interceptors.

Try out the API

Open a new terminal. We need to generate a valid token. You can generate a valid API key from Microgateway using the following command.

If you want to change the authentication token type, go to your open api definition .yaml file in the API definition folder and change the schema as whatever you want and build the project again. You can find more details about security schemas in this Documentation. In my petstore_basic.yaml, I have defined the security extension as api_key under the resource level.

Here the API key will be assigned to the shell variable called TOKEN.

First, let’s try to invoke the API without adding the required header X-API-Key which will be validated inside out interceptor.

curl -X GET "https://localhost:9095/petstore/v1/pet/1" -H "accept: application/json" -H "api_key:$TOKEN" -k

We can see the response below.