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
// HttpRequestMessage -> HttpResponseMessage
let Run(req: HttpRequestMessage) =
  new HttpResponseMessage(HttpStatusCode.OK)

The 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

My each C, R, U, 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
let Run (req:HttpRequestMessage) =
    if req.Method = HttpMethod.Get then
        // ...
    else if req.Method = HttpMethod.Post then
        // ...
    else if req.Method = HttpMethod.Put then
        // ...
    else if req.Method = HttpMethod.Delete then
        // ...
    else
        // ...

Though this approach solves the problem, it comes with another set of challenges. In Object Oriented Programming, we typically use Polymorphism to replace the conditional logic.

Revisiting Function Signature

A request 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 Run function, HttpRequestMessage -> HttpResponseMessage is not completely reflecting the above specification.

Let’s have a look at the limitations of this signature

  • The Run function doesn’t return the HttpRequestMessage. So if we have multiple handlers we are constrained to use either if else if or Polymorphism.

  • It doesn’t represent a handler that doesn’t handle the HTTP request. If the HTTP request is GET, the handler for HTTP POST will not modify the HttpResponseMessage

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 Request and Response as it’s parameters

  • If the handler is not handling the HTTP request, it has to return the unmodified Request and Response along 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
type HttpContext = {
  request    : HttpRequest
  response   : HttpResult
  // ...
}

type WebPart = HttpContext -> Async<HttpContext option>

The Async represents that the WebPart function is a non-blocking asynchronous function and option type models the WebPart which 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.

1
2
// HttpContext -> Async<HttpContext option>
let app = POST >=> OK "HelloSystem.Net.Http

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 Difference

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

  • Transforms HttpRequestMessage from System.Net.Http to HttpRequest of Suave.Http

  • Then create an empty Suave’s HttpContext with the above HttpRequest and call the WebPart (that represents your system).

  • The final step is converting the HttpResult of Suave.Http to HttpResponseMessage of System.Net.Http.

Let’s start from HttpRequestMessage

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
// SuaveAdapter.fsx
let SuaveHttpMethod (httpMethod : System.Net.Http.HttpMethod) =
  match httpMethod.Method with
  | "GET" -> HttpMethod.GET
  | "POST" -> HttpMethod.POST
  | "PUT" -> HttpMethod.PUT
  | "DELETE" -> HttpMethod.DELETE
  | x -> HttpMethod.OTHER x

let SuaveHeaders (headers : HttpRequestHeaders) =
  headers
  |> Seq.map (fun h -> (h.Key, h.Value |> Seq.head))
  |> Seq.toList

let SuaveRawForm (content : System.Net.Http.HttpContent) = async {
  let! content = content.ReadAsByteArrayAsync() |> Async.AwaitTask
  return content
}

let SuaveRawQuery (requestUri : System.Uri) =
  if requestUri.Query.Length > 1 then
    requestUri.Query.Substring(1)
  else
      ""

let NetHeaderValue (headers : HttpRequestHeaders) key =
    headers
    |> Seq.tryFind (fun h -> h.Key = key)
    |> Option.map (fun h -> h.Value |> Seq.head)

let SuaveRequest (req : HttpRequestMessage) = async {
  let! content = SuaveRawForm req.Content
  let host = defaultArg (NetHeaderValue req.Headers "Host") ""
  return {HttpRequest.empty with
            url = req.RequestUri
            ``method`` = SuaveHttpMethod req.Method
            headers = SuaveHeaders req.Headers
            rawForm = content
            rawQuery = SuaveRawQuery req.RequestUri
            host = host}
}

As a convention, I’ve used Net and Suave prefixes in the function name to represent the returning type of System.Net.Http and Suave.Http respectively.

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 HttpContext

1
2
3
4
let SuaveContext httpRequest = async {
  let! suaveReq = SuaveRequest httpRequest
  return { HttpContext.empty with request = suaveReq}
}

Then we need to convert HttpResult to HttpResponseMessage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let NetStatusCode = function
| HttpCode.HTTP_200 -> HttpStatusCode.OK
| HttpCode.HTTP_201 -> HttpStatusCode.Created
| HttpCode.HTTP_400 -> HttpStatusCode.BadRequest
| HttpCode.HTTP_404 -> HttpStatusCode.NotFound
| HttpCode.HTTP_202 -> HttpStatusCode.Accepted
| _ -> HttpStatusCode.Ambiguous

let NetHttpResponseMessage httpResult =
  let content = function
  | Bytes c -> c
  | _ -> Array.empty
  let res = new HttpResponseMessage()
  let content = new ByteArrayContent(content httpResult.content)
  httpResult.headers |> List.iter content.Headers.Add
  res.Content <- content
  res.StatusCode <- NetStatusCode httpResult.status
  res

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 HttpContext.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let SuaveRunAsync app suaveContext = async {
  let! res = app suaveContext
  match res with
  | Some ctx ->
    return (NetHttpResponseMessage ctx.response, ctx)
  | _ ->
    let res = new HttpResponseMessage()
    res.Content <- new ByteArrayContent(Array.empty)
    res.StatusCode <- HttpStatusCode.NotFound
    return res,suaveContext
}

let RunWebPartAsync app httpRequest = async {
  let! suaveContext = SuaveContext httpRequest
  return! SuaveRunAsync app suaveContext
}

Suave Adapter In Action

Let’s see the Suave Adapter that we created in action.

As already there are two great blog posts by Greg Shackles and Michał Niegrzybowski, I am diving directly into Azure functions in F#.

Let me create a new Azure Function application in Azure with the name “TamAzureFun” and then define the first function HelloSuave.

The function.json of 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
{
    "disabled": false,
    "bindings": [{
      "type": "httpTrigger",
      "name": "req",
      "methods": ["get","put","post","delete"],
      "authLevel": "anonymous",
      "direction": "in"
    },{
      "type": "http",
      "name": "res",
      "direction": "out"
    }]
}

Then add the Suave dependency in project.json

1
2
3
4
5
6
7
8
9
{
  "frameworks": {
    "net46": {
      "dependencies": {
        "Suave": "1.1.3"
      }
    }
  }
}

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
// app.fsx
open Suave
open Suave.Successful
open Suave.Operators
open Suave.Filters

let app =
  choose [
      GET >=> OK "GET test"
      POST >=> OK "POST test"
      PUT >=> OK "PUT test"
      DELETE >=> OK "DELETE test"]

The final step is referring the SuaveAdapter.fsx & app.fsx files in the run.fsx and have fun!

1
2
3
4
5
6
7
8
9
10
11
// run.fsx
#load "SuaveAdapter.fsx"
#load "app.fsx"
open SuaveAdapter
open App
open System.Net.Http
open Suave

let Run (req : HttpRequestMessage) =
  let res, _ = RunWebPartAsync app req |> Async.RunSynchronously
  res

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 NewtonSoft.Json & Suave dependencies in project.json

1
2
3
4
5
6
7
8
9
10
{
  "frameworks": {
    "net46": {
      "dependencies": {
        "Suave": "1.1.3",
        "NewtonSoft.Json" : "9.0.1"
      }
    }
  }
}

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
// Suave.Newtonsoft.Json.fsx
open Newtonsoft.Json
open Newtonsoft.Json.Serialization
open System.Text
open Suave.Json
open Suave.Http
open Suave
open Suave.Operators

let toJson<'T> (o: 'T) =
  let settings = new JsonSerializerSettings()
  settings.ContractResolver <- new CamelCasePropertyNamesContractResolver()
  JsonConvert.SerializeObject(o, settings)
  |> Encoding.UTF8.GetBytes

let fromJson<'T> (bytes : byte []) =
  let json = Encoding.UTF8.GetString bytes
  JsonConvert.DeserializeObject(json, typeof<'T>) :?> 'T

let mapJsonWith<'TIn, 'TOut>
  (deserializer:byte[] -> 'TIn) (serializer:'TOut->byte[]) webpart f =
  request(fun r ->
    f (deserializer r.rawForm)
    |> serializer
    |> webpart
    >=> Writers.setMimeType "application/json")

let MapJson<'T1,'T2> webpart =
  mapJsonWith<'T1,'T2> fromJson toJson webpart

let ToJson webpart x  =
  toJson x |> webpart >=> Writers.setMimeType "application/json"

Then define the REST api in app.fsx

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
#load "Suave.Newtonsoft.Json.fsx"
open Suave
open Suave.Successful
open Suave.Operators
open Suave.Filters
open System
open Suave.Newtonsoft.Json

type Person = {
  Id : Guid
  Name : string
  Email : string
}

let createPerson person =
  let newPerson = {person with Id = Guid.NewGuid()}
  newPerson

let getPeople () = [
  {Id = Guid.NewGuid(); Name = "john"; Email = "j@g.co"}
  {Id = Guid.NewGuid(); Name = "mark"; Email = "m@g.co"}]

let getPersonById id =
  {Id = Guid.Parse(id); Name = "john"; Email = "j@g.co"}
  |> ToJson ok

let deletePersonById id =
  sprintf "person %s deleted" id |> OK

let app =
  choose [
    path "/people" >=> choose [
      POST >=> MapJson created createPerson
      GET >=> ToJson ok (getPeople ())
      PUT >=> MapJson accepted id
    ]
    GET >=> pathScan "/people/%s" getPersonById
    DELETE >=> pathScan "/people/%s" deletePersonById
  ]

To keep things simple, I am hard coding the values here. It can easily be extended to talk to any data source

Our 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

1
2
GET /people
GET /people/feafa5b5-304d-455e-b7e7-13a5b3293f77

The HTTP endpoint to call an Azure function has the format

1
https://{azure-function-app-name}.azurewebsites.net/api/{function-name}

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

1
https://{azure-function-app-name}.azurewebsites.net/{header-value-of-X-Suave-URL}

Let’s update SuaveAdapter.fsx to do this

1
2
3
4
5
6
7
8
9
10
11
12
13
let RunWebPartWithPathAsync app httpRequest = async {
  let! suaveContext = SuaveContext httpRequest
  let netHeaderValue = NetHeaderValue httpRequest.Headers
  match netHeaderValue "X-Suave-URL", netHeaderValue "Host"  with
  | Some suaveUrl, Some host ->
    let url = sprintf "https://%s%s" host suaveUrl |> System.Uri
    let ctx = {suaveContext with
                request = {suaveContext.request with
                            url = url
                            rawQuery = SuaveRawQuery url}}
    return! SuaveRunAsync app ctx
  | _ -> return! SuaveRunAsync app suaveContext
}

The final step is updating the run.fsx file to use this new function

1
2
3
4
5
6
7
8
9
10
#load "SuaveAdapter.fsx"
#load "app.fsx"
open SuaveAdapter
open App
open System.Net.Http
open Suave

let Run (req : HttpRequestMessage) =
  let res, _ = RunWebPartWithPathAsync app req |> Async.RunSynchronously
  res

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.

Summary

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

Checking the state of the system and performing a requested action only if certain conditions met, is an indispensable requirement in most of the software we write. Though it is a straightforward thing to do, things will get complex/messier when we need to check multiple conditions.

Recently I encountered such a situation while developing a sample application for my fsharp book. Initially, I solved it with a typical nested if else and then I improved it by applying fsharp’s Partial Active Patterns.

In this blog post , I will be sharing what exactly I did and how it can help you to write an elegant code in fsharp.

Business Domain

Let’s start with a description of the problem domain that we are going to solve.

When an individual visits a restaurant, he can place an order, specifying the list of foods he wants. The foods he ordered will be prepared by the chef and then it will be served.

Preparing a food should satisfy the following conditions

  • The Food should be a part of the order
  • It should not be prepared already
  • It should not be served already

Serving a food should satisfy the following conditions

  • The Food should be a part of the order
  • It should be prepared already
  • It should not be served already

If serving a food completes the order, we should tell that the order is served otherwise we should tell that there are some other foods to be served.

Starting with the types

Let’s start with the types that are needed to solve our problem. If you would like to know why we need to start with the types do check out this wonderful blog post by Tomas Petricek.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type Food = {
  MenuNumber : int
  Name : string
}

type Order = {
  Foods : Food list
}

type InProgressOrder = {
  PlacedOrder : Order
  PreparedFoods : Food list
  ServedFoods : Food list
}

The names of the types and its properties clearly describe what they represent, so let’s get to the crux of the problem straight

Prepare Food

1
2
3
4
5
6
7
8
9
10
11
let prepareFood food ipo =
  if List.contains food ipo.PlacedOrder.Foods  then
    if not (List.contains food ipo.PreparedFoods) then
      if not (List.contains food ipo.ServedFoods) then
          printfn "Prepare Food"
      else
        printfn "Can not prepare already served food"
    else
      printfn "Can not prepare already prepared food"
  else
    printfn "Can not prepare non ordered food"

The if else conditions represent the criteria mentioned in the business domain and for the sake of simplicity we are just writing the action in the console.

Serve Food

Let’s move on to serving food

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let isServingFoodCompletesOrder food ipo =
  let nonServedFoods =
    List.except ipo.ServedFoods ipo.PlacedOrder.Foods
  nonServedFoods = [food]

let serveFood food ipo =
  if List.contains food ipo.PlacedOrder.Foods  then
    if List.contains food ipo.PreparedFoods then
      if not (List.contains food ipo.ServedFoods) then
        if isServingFoodCompletesOrder food ipo then
          printfn "Order Served"
        else
          printfn "Still some food(s) to serve"
      else
        printfn "Can not serve already served food"
    else
      printfn "Can not serve unprepared food"
  else
    printfn "Can not serve non ordered food"

This is called Arrow Anti Pattern and it is obvious that this code is hard to understand and maintain.

It can be improved by using the techniques mentioned in this StackExchange’s answers and also by using the specification pattern from the OO World.

Though the specification pattern solves the problem, it has a lot of code! No offense here but it can be done in a better way.

F# Active Patterns

Active Patterns allow programmers to wrap arbitrary values in a union-like data structure for easy pattern matching. For example, its possible wrap objects with an active pattern, so that you can use objects in pattern matching as easily as any other union type. - F# Programming Wiki

Let’s begin by defining a partial active pattern for NonOrderedFood and UnPreparedFood

1
2
3
4
5
6
7
8
9
let (|NonOrderedFood|_|) order food =
  match List.contains food order.Foods with
  | false -> Some food
  | true -> None

let (|UnPreparedFood|_|) ipo food =
  match List.contains food ipo.PreparedFoods with
  | false -> Some food
  | true -> None

Then for AlreadyPreparedFood and AlreadyServedFood

1
2
3
4
5
6
7
8
9
let (|AlreadyPreparedFood|_|) ipo food =
  match List.contains food ipo.PreparedFoods with
  | true -> Some food
  | false -> None

let (|AlreadyServedFood|_|) ipo food =
  match List.contains food ipo.ServedFoods with
  | true -> Some food
  | false -> None

Finally,

1
2
3
4
5
6
let (|CompletesOrder|_|) ipo food =
  let nonServedFoods =
    List.except ipo.ServedFoods ipo.PlacedOrder.Foods
  match nonServedFoods = [food] with
  | true -> Some food
  | false -> None

With this in place we can rewrite serveFood function as

1
2
3
4
5
6
7
8
9
10
11
let serveFood food ipo =
  match food with
  | NonOrderedFood ipo.PlacedOrder _ ->
    printfn "Can not serve non ordered food"
  | UnPreparedFood ipo _ ->
    printfn "Can not serve unprepared food"
  | AlreadyServedFood ipo _ ->
    printfn "Can not serve already served food"
  | CompletesOrder ipo _ ->
    printfn "Order Served"
  | _ -> printfn "Still some food(s) to serve"

The goal is to have code that scrolls vertically a lot… but not so much horizontally. - Jeff Atwood

Now the code expressing the business logic more clearly

To refactor prepareFood to use the parial active patterns we need one more. So, let’s define it

1
2
3
4
let (|PreparedFood|_|) ipo food =
  match List.contains food ipo.PreparedFoods with
  | true -> Some food
  | false -> None

Now we all set to refactor prepareFood and here we go

1
2
3
4
5
6
7
8
9
let prepareFood food ipo =
  match food with
  | NonOrderedFood ipo.PlacedOrder _ ->
    printfn "Can not prepare non ordered food"
  | PreparedFood ipo _ ->
    printfn "Can not prepare already prepared food"
  | AlreadyServedFood ipo _ ->
    printfn "Can not prepare already served food"
  | _ -> printfn "Prepare Food"

Awesome!

You can get the complete code in my github repository

Summary

F# is excellent at concisely expressing business and domain logic - ThoughtWorks Tech Radar 2012

Refactoring Composition Root

Comments

Last week, I was working on a task which involves populating some PostgreSQL database tables from CSV files. Though this is a straight forward work, I’ve encountered an interesting approach while manipulating a CSV file to adhere some changes in the database schema. In this blog post, I will be sharing what it is and how it made me think better.

Unlike my other blog posts, this post is more on the thought process behind my approach than the code.

The Story

The CSV file that we suppose to import to a database table has the following Structure with 1000 rows

1
2
3
4
5
6
code,value
XAS,0.23
SDR,3.21
WFZ,1.87
........
........

The column name code and value are just for illustration.

The Proposed schema change is introduce a new column called year with a fixed value 2015 for all the rows. So, the expected CSV file would like

1
2
3
4
5
6
year,code,value
2015,XAS,0.23
2015,SDR,3.21
2015,WFZ,1.87
........
........

A Very Simple Task

Now, How can we solve it?

Approach 1 - Don’t try this at your office/home

Let me start with an approach number one

Edit all the rows manually

It is something that you never wanted to see/do. So, let me move on to the next approach without wasting any time here

Approach 2 - Leverage your programming skill

Pick your favorite programming language and whack the CSV file

I believe this would be the approach that came to your mind when you read the problem statement. A typical programmer’s instinct!

So, you picked your programming language ‘X’, what would be the next steps

  • Open the IDE/Editor - Wait for it to load!
  • Create a Project - if required and wait for it also to load!
  • Start typing - and your phone rings
  • Refer library documentation - or Refer Stackoverflow
  • Compile - and wait for it - Ignore this step and wait for a run-time error if your programming language is dynamic
  • Execute - A bug -> Go to Google -> Stack Overflow -> Change the code -> Start again
  • You are done!

I’ve exaggerated some things here. If you don’t agree with any steps, just ignore that step

After 2 to 15 minutes (based on your ability & the ceremony of your programming language) you have solved the problem.

Is it really worth? Well, It depends on the context.

If there are lot of CSV files which require the same change or also few more like this will about to come in the near future, then this effort really makes sense

But, here it is only one file which requires the change. So, I feel it is a complex response to a simple problem

Approach 3 - Use a tool

Use a shiny CSV management tool to make the changes

It is slightly better approach than the previous one but it also has its own downsides

  • Googling to find the tool
  • Download it - Your office firewall is blocking that site! / Registration on the tool site / Requires Java x.x version
  • Open the CSV file.
  • Refer the tool’s documentation
  • Get the job done

You can also Microsoft Excel to achieve this. But again a heavy solution to solve a simple problem!

There should be a simple approach! That’s what we are going to see next.

Approach 4 - Find And Replace

Just use Find and Replace in an advanced editor

This approach involves just three steps

  • Open the CSV file in an advanced text editor (notepad++, atom, sublime text, etc.,)
  • Select all the text and press tab
  • Open Find and Replace. Find for tab and replace it with 2015,

That’s it!

Summary