Recently Microsoft Azure has made F# as a first-class citizen to write Azure Functions. As F# is a functional-first programming language, I feel Azure Functions and F# would be a match made in heaven.
In this blog post, you are going to experience a scaled up version of Azure Functions in F# using Suave
What’s in the Function Signatures?
In a functional programming language, we define small functions that do one thing well and then we compose them together to represent the solution. To compose functions, we need to be thoughtful while designing the signature of a function.
Let’s see the signature of an Azure Function in F#
1 2 3
Run function takes a
HttpRequestMessage and returns the
HttpResponseMessage. This signature is simple, but it has a limitation. The limitation has been showcased in the templates directory of Azure Webjobs SDK
D are in different functions. Well, there is nothing wrong here. These templates are suitable for getting started in Azure Functions. But what will you do if you have a requirement to expose
CRUD of a resource as an Azure Functions?
One option is to define each part of the
CRUD as separate Azure Functions (as defined by the templates). If you choose to go by this, you will have four different endpoints and I am sure your client code will have a hard time to consume these endpoints. In addition to this, you will also need to manage four things to satisfy your one requirement.
The other option is putting the
CRUD inside a single function.
1 2 3 4 5 6 7 8 9 10 11
Revisiting Function Signature
handler looks for some condition to be meet in the incoming HTTP request, and if the predicate succeeds, it modifies the HTTP response.
The signature of the
HttpRequestMessage -> HttpResponseMessage is not completely reflecting the above specification.
Let’s have a look at the limitations of this signature
Runfunction doesn’t return the
HttpRequestMessage. So if we have multiple
handlers we are constrained to use either
if else ifor Polymorphism.
It doesn’t represent a handler that doesn’t handle the HTTP request. If the HTTP request is
POSTwill not modify the
The better signature would have the following to describe a handler in a better way
The handler has to be pure function that takes both
Responseas it’s parameters
If the handler is not handling the HTTP request, it has to return the unmodified
Responsealong with an indicator saying that it didn’t handle the request.
It’s where the Suave library shines. Suave defines a type called
WebPart with the signature to model the
handler with the above-said expectations.
1 2 3 4 5 6 7
Asyncrepresents that the
WebPartfunction is a non-blocking asynchronous function and
optiontype models the
WebPartwhich doesn’t handle the HTTP request
The real power of Suave is its set of combinators to manipulate route flow and task composition. You can define an API in Suave that only handles HTTP
POST requests and returns
Hello as text without typing too much.
To learn more about the Suave combinators refer my blog post on Building REST API in suave
If you notice the binding
app itself is a
WebPart (which in turn a function) with the signature
HttpContext -> Async<HttpContext option>. So, you can call this function in your application code and project the output of the function to any output medium that you wish.
The Azure Functions do an incredible job in helping you to define a part of your system as a function. Suave takes it to the next level by helping you to define your system as function.
In nutshell, Suave complements Azure Functions and helps you to define your system as a Serverless Function
Creating a Suave Adapter
So, to scale up Azure Functions using Suave, all we need is an adapter.
The adapter does the following
Then create an empty Suave’s
HttpContextwith the above
HttpRequestand call the
WebPart(that represents your system).
The final step is converting the
Let’s start from
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
As a convention, I’ve used
Suaveprefixes in the function name to represent the returning type of
I hope that these functions are self-explanatory, so let’s move on the next step.
To keep it simple, I’ve ignored other HTTP Methods like PATCH, HEAD, etc.
The next step is creating Suave
1 2 3 4
Then we need to convert
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
To keep it simple, I’ve ignored other HTTP StatusCodes
The final step is putting these functions together and run the
WebPart function with the translated
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Suave Adapter In Action
Let’s see the Suave Adapter that we created in action.
Let me create a new Azure Function application in Azure with the name “TamAzureFun” and then define the first function
HelloSuave has to be updated with the
methods property to support different HTTP request methods.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Then add the
Suave dependency in
1 2 3 4 5 6 7 8 9
Let’s start simply by defining small API (system) that handles different types of HTTP methods.
1 2 3 4 5 6 7 8 9 10 11 12
The final step is referring the
app.fsx files in the
run.fsx and have fun!
1 2 3 4 5 6 7 8 9 10 11
Let’s make some HTTP requests to test our implementation.
Suave is rocking!
Creating a REST API in Azure Functions
We can extend the above example to expose a REST end point!
In Suave a REST API is a function.
Create a new Azure Function
HelloREST and add
Suave dependencies in
1 2 3 4 5 6 7 8 9 10
To handle JSON requests and responses, let’s add some combinators
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
Then define the REST api in
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
To keep things simple, I am hard coding the values here. It can easily be extended to talk to any data source
SuaveAdapter has capable of handling different HTTP methods and but it hasn’t been programmed to deal with different paths.
Here in this example we need to support two separate paths
The HTTP endpoint to call an Azure function has the format
At this point of writing it doesn’t support multiple paths. So, we need to find a workaround to do it.
One way achieving this is to pass the paths as a Header. Let’s name the Header key as
X-Suave-URL. Upon receiving the request we can rewrite the URL as
SuaveAdapter.fsx to do this
1 2 3 4 5 6 7 8 9 10 11 12 13
The final step is updating the
run.fsx file to use this new function
1 2 3 4 5 6 7 8 9 10
Serverless REST API in Action
This blog post is a proof of concept to use Suave in Azure Functions. There are a lot of improvements to be made to make it production ready. I am planning to publish this as a NuGet package based on the feedback from the community.
*PLEASE* Microsoft, stop saying #fsharp is great for "financial applications and stuff like that". It's a bloody general purpose language.— Isaac Abraham (@isaac_abraham) June 7, 2016
The complete source code is available in my GitHub repository.
Are you interested in learning more about F#?
I’m delighted to share that I’m running a tutorial at Progressive F# Tutorials 2016, London on Dec 5, 2016. I’m excited to share my experiences with Suave and help developers to understand this wonderful F# library.
The Progressive F# Tutorials offer hands-on learning for every skill set and is led by some of the best experts in F# and functional programming