DEV Community

Cover image for Serverless REST API with Azure Functions, Node, JSON and Azure SQL
Davide Mauri for Microsoft Azure

Posted on • Originally published at devblogs.microsoft.com

Serverless REST API with Azure Functions, Node, JSON and Azure SQL

Javascript / Typescript (and thus Node) are, among Full-Stack and Back-End developers, one of the most common choices to create scalable, elegant, high-performance, REST API to be used by the most diverse clients.

Azure Functions are another pretty popular solution that developers use to create scalable solution without having to deal with all the infrastructural woes, as it just allow you to code you own function, deploy it and….done! No IIS or Apache to configure and monitor, no headaches to setup, configure and maintain a load-balanced cluster….just the sheer joy of coding!

As a developer I'd love to be able to use Node and Azure Functions with the database of my choice which, as you can already guess, it Azure SQL. I have already explained extensively (here and here, for example) why I think Azure SQL is just the perfect database for the cloud, so I decided to try to create a REST endpoint just using Azure Functions, Azure SQL and Node.

I'm quite new to Node so I thought it could be helpful for anyone in my situation to share what I have learned. Here we go!

Recipe for KISS

I really wanted to follow the KISS principle, so I decided to avoid any additional library and just go with Tedious, the most widely used Node package for SQL Server / Azure SQL. I also wanted to do everything in the most javascript-friendly way possible, which means manipulating objects and JSON instead of SQL statements or anything that would remind me that behind the scene I have a (post-)relational database. From this point of view, NoSQL databases usually offer a great user experience as everything is already JSON, and so there is basically nothing special to do to manipulate data.

You send JSON, you get JSON, as simple as that.

With Azure SQL is possible too and, on top of that, you'll get all the additional goodness that Azure SQL offers.

Azure Function and Tedious

First of all, you need to create an Azure Function and this can be easily done using the Azure Function CLI. Make sure you have it installed and than simply run

func init --worker-runtime node --language javascript
Enter fullscreen mode Exit fullscreen mode

in an empty folder that you'll use as Azure Function working folder. Then add a new function

func new --template HttpTrigger --name customer
Enter fullscreen mode Exit fullscreen mode

Everything is now ready to be used, and you can start Azure Function runtime locally just by running

func start
Enter fullscreen mode Exit fullscreen mode

Azure Function will start to listen on localhost, and you can already start to use the created REST endpoint by issuing a GET request, for example, at

http://localhost:7071/api/customer
Enter fullscreen mode Exit fullscreen mode

using your a REST client like cUrl or Insomnia (or your favorite one). The REST endpoint doesn't do much at the moment, and you still need to connect it to Azure SQL. To do that you have to install the Tedious package (make sure you are in the create Azure Function folder, where you can see also the file host.json)

npm install tedious    
Enter fullscreen mode Exit fullscreen mode

and you're good to go. You can now open your favorite editor (Visual Studio or Visual Studio Code in my case) and start to create a REST endpoint that will handle HTTP request to implement CRUD operation for our sample Customer endpoint. I won't enter into detail of how to use Tedious as it is pretty simple, and also it has quite good documentation on its website; it will be enough to say that you just have to follow to usual pattern:

  • Connect to Azure SQL via the Connection object
  • Execute a command, via the Request object
  • Consume the resultset

Hey, it doesn't work!

Now, there is only one problem here. If you try to use Tedious with the default Azure Function template, which look like this:

module.exports = async function (context, req)
{
    /*
     * Business Logic here
     */
    responseMessage = { customerId: 123, name: "Davide" }

    context.res = {       
        body: responseMessage
    };
}
Enter fullscreen mode Exit fullscreen mode

it won't work. Even worse, it will work without any error, but you'll never get a result.

The reason, as per my (limited, as I'm pretty new to this) understanding, is that Tedious doesn't support the async/await pattern which is instead used by default by Azure Functions. The solution is to remove the async keyword from the function definition and then make sure the HTTP response is properly sent back by setting it in the context object, provided by Azure Function runtime. Once the HTTP response is ready to be sent, a call to context.done() is needed to inform Azure Function that work is done. Everything is explained here:

Azure Functions JavaScript developer guide: context.done method

Here's the pseudo-code needed to make it work (GitHub repo with fully working code is also available, just keep reading)

define Connection object
define Request object
  if Request fails 
    set HTTP status to 500
  once Request is done
    put Request result into context.res
  call context.done()
open Connection
  if Connection fails 
    set HTTP status to 500
    call context.done()
  else
    execute Request
Enter fullscreen mode Exit fullscreen mode

Once you know that, is pretty easy.

Ok, enough with columns and rows

As written at the beginning, as a developer I feel much more comfortable manipulating a JSON object than tables with columns and rows, so I'd love to be able to get JSON from Azure SQL and send back JSON to the database. Thanks to Azure SQL native JSON support, I can do that. For example, to return a JSON array of all customers that I should return as result of an HTTP GET request I can just do this:

SELECT 
    [CustomerID] AS 'Id', 
    [CustomerName] AS 'Name'
FROM 
    [Sales].[Customers] 
FOR JSON PATH
Enter fullscreen mode Exit fullscreen mode

and the result would be something like:

[
    {
        "Id": 832,
        "Name": "Aakriti Byrraju"
    },
    {
        "Id": 836,
        "Name": "Abel Spirlea"
    },
    {...}
]
Enter fullscreen mode Exit fullscreen mode

This is great for receiving JSON data from Azure SQL. But what about sending a JSON so that it will be then stored into an existing table? Easy as before. Let's say this is the JSON you'll be sending to Azure SQL:

{
    "CustomerName": "John Doe",
    "PhoneNumber": "123-234-5678",
    "FaxNumber": "123-234-5678",
    "WebsiteURL": "http://www.something.com",
    "Delivery": {
        "AddressLine1": "One Microsoft Way",
        "PostalCode": 98052
    }
}
Enter fullscreen mode Exit fullscreen mode

then this is the T-SQL code you can use to turn JSON into a table that it can be easily inserted into existing structures:

SELECT 
    * 
FROM
    OPENJSON(@Json) WITH
    (       
        [CustomerName] NVARCHAR(100), 
        [PhoneNumber] NVARCHAR(20), 
        [FaxNumber] NVARCHAR(20), 
        [WebsiteURL] NVARCHAR(256),
        [DeliveryAddressLine1] NVARCHAR(60) '$.Delivery.AddressLine1',
        [DeliveryAddressLine2] NVARCHAR(60) '$.Delivery.AddressLine2',
        [DeliveryPostalCode] NVARCHAR(10) '$.Delivery.PostalCode'   
    )
Enter fullscreen mode Exit fullscreen mode

That's it!

This way we can use the most convenient or correct structures for each language and tool we are using. JSON for Javascript and Tables for SQL.

If you want, of course, you could also store JSON also as-is, without the need to turn it into a table, but that will be less efficient. Depending what you want and need to do, choose what's the best for you. In case you decide to store JSON as-is, remember that you can also create indexes on JSON documents. If you are unsure which strategy would be the most suitable for your scenario - JSON or proper tables - this article can surely help you decide: JSON in your Azure SQL Database? Let’s benchmark some options!

Conclusion

Using Node with Azure SQL has never been easier thanks to JSON acting as a trait d'union between the two different worlds. It finally seems that the days of impedance mismatch are finally gone. So it's now time to fully take advantage of two truly amazing technologies like Node and Azure SQL.

With Azure SQL you can have Row-Level Security, Change Tracking, Encryption, Columnstore, Lock-Free tables, and much more....all usable via JSON integration.

Give it a test drive yourself, by deploying on Azure the code available here:

Creating a REST API with Azure Functions, Node and Azure SQL GitHub Code Repo

Have fun!

Top comments (0)