An Exploration of REST API Handling with Ballerina

Pasidalee Dissanayake
5 min readMay 1, 2023

This article delves into Ballerina’s capabilities in handling REST APIs. Ballerina is a modern, open-source programming language designed specifically for building cloud-native microservices with ease. It provides built-in support for handling HTTP/REST-based services, making it an ideal choice for building RESTful APIs.

HTTP (Hypertext Transfer Protocol) is the foundation of communication on the World Wide Web. It’s a request-response protocol, which means that a client sends a request to the server, and the server responds with the requested data. Ballerina is well-equipped to handle this type of communication.

In Ballerina, services are the fundamental building blocks for creating APIs and handling network communications. At its core, an HTTP service in Ballerina is a network-based service that listens for incoming HTTP requests and returns an HTTP response. The service is defined using a Ballerina source file that contains a service definition and the resources that are associated with each method.

A service in Ballerina is defined with the “service” keyword, followed by the service name and its implementation. Services are associated with endpoints that specify the address and protocol used to communicate with the service.

service / on new http:Listener(9090) {   
resource function get getsum(int a, int b) returns int {
return a + b;
};
}

Let’s examine each of these components.

Service Name

The service name is the base path or absolute resource path of an HTTP service, and it is optional. If left empty, the base path defaults to “/”.

Listener Object

The listener object provides an instance of “http:Listener” to bind to a specific host/port. The listener is responsible for listening for incoming HTTP requests and passing them on to the appropriate resource for processing. It is defined using the “http:Listener” type. When an HTTP request is received by the listener, it passes the request on to the appropriate resource for processing.

Let’s move on to exploring the resource functions. The function that handles the logic of the service is called the resource function, and it is associated with a specific HTTP method and URL resource. The resource function is defined using the resource keyword.

Inside the resource function, you can write the logic for handling the incoming HTTP request and constructing the outgoing HTTP response. This might involve parsing the request body, querying a database, or performing some other business logic, returning the response.

service / on new http:Listener(9090) {   
resource function get getsum(int a, int b) returns int {
return a + b;
};


}

Resource

A resource represents a specific sub-path that can be accessed in relation to the service base path.

Accessor

An accessor is the HTTP method used to access a resource. Each resource can have only one accessor. However, if we need to support multiple HTTP methods for a single resource, we can define distinct service resources with the same name and different accessors. The “default” accessor is used to dispatch all requests with the resource path, regardless of the HTTP method.

Name

The name represents the path of the resource in relation to the service base path. We can provide hierarchical values, such as “getSum”. In this case, the final path to the resource would be “/getSum”. The “.” name is used to represent the service itself in a resource. Therefore, requests that are directly sent to the base path will be dispatched to this resource.

Path Param

Path parameters can be used to extract dynamic values from the request path. Ballerina’s HTTP module allows for adding path parameters to a resource method by including the parameter type and name in the resource path, such as “data/[int number]”. The supported types for path parameters in Ballerina are string, int, float, boolean, and decimal.

service / on new http:Listener(9090) {
resource function get data/[int number]() returns int{
//Returns an integer value by adding one to the value of number path parameter
return number+1;
}
}

Query Param

The “query parameter” refers to the part of a URL that includes the search criteria. The name of the argument should match the query key and its value is determined at runtime by extracting it from the URL. The parameter type must be one of the types: string, int, float, boolean, decimal, and array. Query parameters can also be optional (e.g., (int? age)) and have default values (e.g., (int age = 18)). It’s recommended to retrieve query parameters as resource arguments because it’s easier and more efficient. Alternatively, you can also use the “http:Request” methods to retrieve query parameters.

service / on new http:Listener(9090) {   
resource function get getsum(int a, int b) returns int {
return a + b;
};
}

Payload Param

HTTP service payload data binding allows accessing the request payload using a resource signature parameter. The resource parameter type should be a sub-type of anydata. By default, parameters with the map, array, tuple, table, record, and XML types are mapped to the payload. For other types, the “@http:Payload” annotation is required. and If the signature includes more than one of the aforementioned types, the “@http:Payload” should be used to resolve the ambiguity. This behavior is limited to the POST, PUT, PATCH, DELETE, and DEFAULT accessors.

type Person readonly & record {|
string name;
string age;
|};

service / on new http:Listener(9090) {
resource function post body(@http:Payload Person person) returns json {
return {"Person": person};
}
}

Header Param

The “@http:header” annotation enables the retrieval of header values from the request. This annotation can be used to annotate a resource parameter. The parameter name must match the header name, but if there’s a mismatch, the header name can be specified in the annotation configuration.

service / on new http:Listener(9090) { 
//Single header value
resource function post data(@http:Header string accept) {
}
//Multiple header values
resource function post data(@http:Header {name: "Accept"} string[] accept) {
}
//The http:Header object contains all the headers
resource function get hello3(http:Headers headers) {
String|error referer = headers.getHeader("Header1");
String|error accept = headers.getHeader("Header2");
String[] keys = headers.getHeaderNames();
}
}

Return Type

The return type is optional and can be of type anydata, “http:Response”, “http:ResponseCodeResponse”, error, or nil.

resource function get data() returns http:Response|string|error?{
//function returns http:Response or string or error or nil
}
  • anydata: An anydata return value would be returned with an HTTP status code 200 OK
  • nil: if the resource wants to return nothing, the listener will return 202 Accepted response.
  • error: an error return would be returned with an HTTP status code 500 Internal Server Error.
  • http:ResponseCodeRespon: Ballerina has built-in records for all status codes.

In summary, an HTTP service in Ballerina is a network-based service that listens for incoming HTTP requests and returns an HTTP response. The service also includes an endpoint, a listener, and a function that handles the logic of the service. By understanding the various components that make up an HTTP service in Ballerina, you can begin to build robust and scalable microservices-based applications that can handle a wide range of HTTP requests and responses.

--

--

Pasidalee Dissanayake

Undergraduate at Faculty of Information Technology, University of Moratuwa