Codementor Events

[GUIDE] Building a REST API in Low-code

Published Mar 19, 2021Last updated Sep 14, 2021
[GUIDE] Building a REST API in Low-code

REST API development has many approaches and there are 100’s of different API development tools to choose from, making it pretty easy to get lost in the process.

In this article, we cover how to build and host and API in Linx, a low-code development platform that gives us a quick and easy way to develop and host APIs.

1. Application Specifications

The Linx application will contain a REST API hosted on a Linx application cloud server. The web service will contain an operation to return a full list of mock ‘products’ from a SQL server cloud database as well as an operation to return a specific ‘product’ based on a parameter. The web service will be secured via the API Key authentication scheme.

Database specification
The Linx application will connect to a SQL Server cloud database hosted on an Azure instance. For demonstration sake, the following table exists that holds records related to mock “products”. These records have been imported into the database using Linx:
image15.png

These records will be retrieved from the database and returned in a http response by Linx, filtering for a specific ‘product’ will be achieved with SQL.

API specification
The REST web service will contain the below operations
Screenshot 2021-03-19 at 14.12.34.png


2. Building the Application

Building the described application in Linx and hosting it involves the following stages:

  1. Create a new application
  2. Add the relevant plugin libraries
  3. Define the web service operations
  4. Add custom processing logic
  5. Deploy and activate

Create a new application

Creating a Linx application is easy – with just a single click, the base skeleton of the application is created for you. You are then able to add services, functions and types to bring your application to life.

Install the relevant plugin libraries

Linx is based on a plugin architecture that can be thought of as common libraries which contain functions and data types related to that area of functionality. For my application, I need to integrate with a database and expose a REST web service:

Screenshot 2021-03-19 at 14.15.24.png

image32.png

Creating and defining a REST web service

To add a REST web service to my Linx application, I can just make use of the SimpleRESTHost service (part of the REST plugin). This allows me to quickly create and configure REST operations. The service can be added to my application by dragging the SimpleRESTHost service from the plugins panel into the Solution Explorer. This will create a base skeleton of an API for me to work with.

image21.png

Next, I need to define the Base URL on which the API will be hosted on. The specific paths of each operation will be appended to this Base URL. In my case, I’m are going to initially test the web service locally by hosting it in the actual Linx Designer, this can be done by setting the Base URL to the below:
http://localhost:8080/myapi

image4.png

Defining the operations

Now that the base configuration is set up, I can now begin to add my operations to the web service. First I’m going to create the ‘GetProduct’ operation and configure it with the below properties:

image6.png

For now, I’m just going to leave the ‘response body’ type as a ‘String’ to make a “Hello World” request.The ‘GetProduct’ operation will then be created and visible in the Linx Designer.

Adding logic to the operation

I can now begin to add logic to return our response. To start, I am just going to return a simple message “Hello World!” to ensure I’ve set up everything correctly so far.

To do this, I can just add a SetValue function from the plugins panel onto the ‘GetProduct’ operation canvas. This function allows you to alter the value of a data reference, in my case I am going to alter the response body property of the ‘GetProduct’ operation and return a simple text message “Hello World!”.

image2.png

Testing the service

I can now test out my Linx web service by debugging the service in the Linx Designer. This will spin up a locally accessible web service that I can test out and make requests against as well as seeing the process flow.

Once the service debugging has started, I can make a request to the below endpoint in my browser:

http://localhost:8080/myapi/products/this-is-my-testid

image5.png

If successful, a string response containing the text “Hello World!” will be returned. Now that I’ve confirmed the web service is functioning correctly, lets add some real-world functionality.

Define a ‘product’ object

First, I’m going to configure the operation to return a ‘product’ object. To do this, I need to define a custom type in Linx which will contain the relevant fields:

{
“id”: “0bdec814-6f7f-4730-b95a-b1518fbfd6fb”,
“name”: “Clothing Jeans”,
“code”: “#693”,
“price”: 516.43,
“vendor”: “Mayert and Sons”,
“last_updated”: “2020-05-30T22:00:00.0000000Z”
}

To define such an object to work with in Linx, you are able to either import the above JSON string into Linx and a custom type mapping to those fields will be created. Or you have the option of manually creating the relevant fields using the type editor.

image19.png

Update response type of operation

Once I’ve defined the ‘product’ type, I am able to reference this structure throughout the application. In my case, I am going to be returning this ‘product’ type as the response of our ‘GetProduct’ operation. To do this, I can just open up the operations editor of the SimpleRESTHost and alter the response body type to be of the custom type ‘product’ that I just created.

image8.png

Set response fields

Now if I go back to the SetValue function in the ‘GetProduct’ operation, Linx has picked up the operation changes and now I am able to set the individual fields of the response body using the field editor.

image3.png

To test it out, I’m going to hard code some values for a mock ‘product’ in the SetValue.

image7.png

Debug service with changes

When I debug my web service again and make a request using a browser or tool such as Postman. The response data will contain a JSON object containing the fields of my ‘product’.

image14.png

Now that I’ve confirmed the web service is functioning correctly and the response object has been configured, lets add the final piece to this operation, namely retrieving a particular record from the database.

Adding an ExecuteSQL function

To execute such a query against our database, I can just use the ExecuteSQL function which is part of the database plugin. I can just add this function to our ‘GetProduct’ operation above the SetValue.

Creating a connection to the database

Next, I first need to create a connection to the database, this can be done with the connection editor. This will build up a connection string which will be used by the ExecuteSQL function when connecting to the cloud database.

image18.png
image9.png

Creating a SQL query

Now that I’ve established a successful connection to the database, lets add a query to filter the ‘products’ for a record matching the {id} parameter passed in with the request URL. With Linx, you are able to auto generate query statements, in my case, I am going to generate a ‘SELECT’ from the ‘products’ table. This will create a basic ‘SELECT * FROM’ statement. For my particular use case, I am going to add a query condition to the SQL statement which will filter for records with the id field matching the ‘id’ parameter passed in with the request. The id parameter is available as a variable which can then just be dragged into my query. The names of the output fields will be auto-populated by Linx.

image11.png

Setting the database return type

Next, I am going to configure the output type of the ExecuteSQL to only return a single row (as product ids are unique), and if none are found then the default value types will be returned. This can be done by setting the output type to ‘first row, else empty’.

image13.png

Setting the response of the operation

Now that I’ve setup our database connection and query, I can now return the results of my database query as the response body by referencing the fields returned from the database. To do this, I just need to modify the SetValue and instead of hardcoding values as the response, for each field, I can just reference the appropriate field returned from the database.

image31.png


3. Debug the Service

Now I have a Linx application that contains a web service operation which takes in an {id} of a ‘product’, queries the database for a matching record and returns the result. Let’s take it for a spin!

Using Postman, I can make a request to the endpoint:

http://localhost:8080/myapi/products/{id}
Where {id} is GUID that matches a record in the database.

image20.png
A ‘product’ is returned containing the details of a matching ‘product’ record from the database.


4. Returning All Products

Now that I’ve created my ‘GetProduct’ operation and confirmed it is working as expected. Lets follow the same steps but create an operation that returns all of the products from our database.

In this operation, a request will be made to the ‘/products’ path. The database will be queried for all product records, these records will then be returned in the response as a collections of ‘product’ details.

Much like before I can just simply add an additional ‘GetProducts’ operation with the path ‘/products’. In this case, the operation will return a list of ‘product’ in the response body. To configure the operation to do this, set the response body type as ‘List<String>’ and then using the list type editor, set it as ‘List<product>’.

image26.png

image10.png

Retrieving all products from the database

As I did before, we can add an ExecuteSQL function to the operation and use the autogenerated statement to return all the records from the database, row by row. You can also copy the ExecuteSQL function from the ‘GetProduct’ operation and alter the query statement and return options properties.

image10.png

Adding to the products list response

Since the response body type is a list of ‘product’, I need to build up the list of products row by row. This is achieved by using an AddToList function instead of a SetValue. For each row returned by the query, the particular ‘product’ details are then added to the response body list.

image22.png

image25.png

Debugging the service

When a call is made to the ‘/products’ operation, a JSON structured List containing all ‘products’ will be returned.

image38.png


5. Adding Authentication

Now that I’ve got a public and open API, lets add some security to limit who can access the data. In this case I’ll add some basic API Key authentication to the operations. When a request is made, Linx will extract the ‘Authorization’ header from the request, this will then be available to use in my authentication event to validate the API Key against a value stored as a constant (this could also be things such a database record, file record etc.).

To add API Key authentication to an operation, I can just select the ‘API Key’ option in the SimpleRESTHost properties:

image12.png

This will create an “Authenticate” event which will be visible in the Solution Explorer’. Authentication logic can be added to this event to validate incoming requests before any operation is executed.

Adding authentication logic

In my case, I am just going to compare the API Key submitted with the request against a value stored as a Linx application’s $.Settings (or constant). If the value matches, the result of the authentication event is set, if it does not match, then by default the operation will return a (401) – Unauthorized response.

I first need to create a constant to store our API Key in, this is done by adding a ‘$.Setting’ to the Linx application which will be available to reference across my Linx application.

image23.png

Then I need to add some decision-making logic to validate the API Key by using an IfElse decision making function.

image30.png

Applying the authentication to an operation

Next, I can attach the security scheme to my operations by editing the particular operation and applying the scheme:

image24.png

Testing the authentication

I can test out the authentication scheme by debugging and making a request without an API Key header, I will receive a ‘(401) – Unauthorized’ error.

image29.png

When I make a request, if I include an API Key which matches the constant in the Linx application in the ‘Authorization’ header, I should be successfully authenticated and the list of products returned.

image34.png


6. Deploying to Production

Now that I have a functional Linx web service with security applied, lets deploy my web service into production so I can expose it to the external world. This is done by deploying the Linx application to my Linx application cloud server where it will be hosted and activated. Once this is done, requests can be made from anywhere against the API.

Altering base URL
First I need to alter to Base URL to host it on the cloud server which can be done with the below setting:

https://+:8080/myapi
The ‘+’ character will grab the cloud server instance name once deployed.

Deploying to the cloud server
Next, I can simply deploy to my cloud instance of the Linx application server by deploying straight from the Linx Designer. Next, I just need to activate the web service. And now I can make request from anywhere against the API.

image39.png


7. Generating documentation for our API

Now that I’ve secured and deployed our API, in order for people to use it, they need to understand the rules. To expose these rules, I can automatically generate the documentation for my Linx API by setting the API Documentation property of the SimpleRESTHost. In my case we are going to generate the documentation in Swagger.

image28.png

Once I’ve configured the changes, I need to deploy again to activate the changes. Once deployed, users can make a request to the documentation endpoint which is hosted on: {base URL}/swagger

image37.png

You’re done! And that’s how simple it is to build an API using Linx.

Original article https://linx.software/the-ultimate-guide-to-building-a-low-code-rest-api-how-to-guide/

Discover and read more posts from Anthony Morris
get started