import ballerina/http;
endpoint http:Listener hbrEP {
    port:9090
};endpoint http:Client locationEP {
    targets: [
        {
            url: "http://www.mocky.io"
        }
    ]
};endpoint http:Client weatherEP {
    targets: [
        {
            url: "http://samples.openweathermap.org"
        }
    ]
};
@http:ServiceConfig {
    basePath:"/hbr"
}
service<http:Service> headerBasedRouting bind hbrEP {
    @http:ResourceConfig {
        methods:["GET"],
        path:"/route"
    }
    hbrResource (endpoint conn, http:Request req) {
        http:Request newRequest = new;
        if (!req.hasHeader("type")) {
            http:Response errorResponse = new;
            errorResponse.statusCode = 500;
            json errMsg = {"error":"'type' header not found"};
            errorResponse.setJsonPayload(errMsg);
            _ = conn -> respond(errorResponse);
            done;
        }
        string nameString = req.getHeader("type");        (http:Response|http:HttpConnectorError|()) response;
        if (nameString == "location") {
            response = locationEP -> post("/v2/594e12271100001f13d6d3a6", newRequest);
        } else {
            response = weatherEP -> get("/data/2.5/weather?lat=35&lon=139&appid=b1b1", newRequest);
        }        match response {
            http:Response clientResponse => {
                _ = conn -> respond(clientResponse);
            }
            http:HttpConnectorError err => {
                http:Response errorResponse = new;
                errorResponse.statusCode = 500;
                errorResponse.setStringPayload(err.message);
                _ = conn -> respond(errorResponse);
            }
            any => {
                http:Response errorResponse = new;
                errorResponse.statusCode = 500;
                json errMsg = {"error":"unexpected response received"};
                errorResponse.setJsonPayload(errMsg);
                _ = conn -> respond(errorResponse);
            }
        }
    }
}

Header Based Routing

The Header-Based Router service reads a particular Header of a request and routes it to a specific recipient based on the Header value.

import ballerina/http;
endpoint http:Listener hbrEP {
    port:9090
};

Attributes associated with the service endpoint is defined here.

endpoint http:Client locationEP {
    targets: [
        {
            url: "http://www.mocky.io"
        }
    ]
};
endpoint http:Client weatherEP {
    targets: [
        {
            url: "http://samples.openweathermap.org"
        }
    ]
};
@http:ServiceConfig {
    basePath:"/hbr"
}
service<http:Service> headerBasedRouting bind hbrEP {

Service is invoke using BasePath value (/hbr).

    @http:ResourceConfig {
        methods:["GET"],
        path:"/route"
    }
    hbrResource (endpoint conn, http:Request req) {

The http:resourceConfig{} annotation with GET method declares the HTTP method.

        http:Request newRequest = new;

Create new outbound request to handle client call.

        if (!req.hasHeader("type")) {
            http:Response errorResponse = new;
            errorResponse.statusCode = 500;
            json errMsg = {"error":"'type' header not found"};
            errorResponse.setJsonPayload(errMsg);
            _ = conn -> respond(errorResponse);
            done;
        }

Checks whether ‘type’ header exists in the request.

        string nameString = req.getHeader("type");

Native function getHeader() returns header value of a specified header name.

        (http:Response|http:HttpConnectorError|()) response;
        if (nameString == "location") {
            response = locationEP -> post("/v2/594e12271100001f13d6d3a6", newRequest);
        } else {

“post” represent the POST action of HTTP connector. Route payload to relevant service.

            response = weatherEP -> get("/data/2.5/weather?lat=35&lon=139&appid=b1b1", newRequest);
        }

“get” action can be used to make http GET call.

        match response {
            http:Response clientResponse => {
                _ = conn -> respond(clientResponse);
            }
            http:HttpConnectorError err => {
                http:Response errorResponse = new;
                errorResponse.statusCode = 500;
                errorResponse.setStringPayload(err.message);
                _ = conn -> respond(errorResponse);
            }
            any => {
                http:Response errorResponse = new;
                errorResponse.statusCode = 500;
                json errMsg = {"error":"unexpected response received"};
                errorResponse.setJsonPayload(errMsg);
                _ = conn -> respond(errorResponse);
            }
        }
    }
}

Native function “respond” sends back the inbound clientResponse to the caller if no any error is found.

$ ballerina run header-based-routing.bal
ballerina: initiating service(s) in 'header-based-routing.bal'
ballerina: started HTTP/WS server connector 0.0.0.0:9090
$ curl -v http://localhost:9090/hbr/route -H "type:location"
{
    "name": "Colombo,Sri Lanka",
    "longitude": -556.49,
    "latitude": 257.76,
    "altitude": 230,
}
$ curl -v http://localhost:9090/hbr/route -H "type:weather"
{"coord":{"lon":139.01,"lat":35.02},"weather":[{"id":800,
"main":"Clear","description":"clear sky","icon":"01n"}],
"base":"station","main":{"temp":25.51,"clouds":{"all":0},
"wind":{"speed":5.52,"deg":311},"dt":148579296788555885,
"id":1907296,"name":"Tawarano","cod":200}}