Skip to content

Functional web synergy with F# and OWIN

December 22, 2014

Before we get started I’d just like to mention that this post is part of the truly excellent F# Advent Calendar 2014 which is a fantastic initiative organised by Sergey Tihon, so big thanks to Sergey and the rest of the F# community as well as wishing you all a merry christmas!

Introduction

Using F# to build web applications is nothing new, we have purpose built F# frameworks like Freya popping up and excellent posts like this one by Mark Seemann. It’s also fairly easy to pick up other .NET frameworks that weren’t designed specifically for F# and build very solid applications.

With that in mind, I’m not just going to write another post about how to build web applications with F#.

Instead, I’d like to introduce the F# community to a whole new way of thinking about web applications, one that draws inspiration from a number of functional programming concepts – primarily pipelining and function composition – to provide a solid base on to which we can build our web applications in F#. This approach is currently known as Graph Based Routing

Some background

So first off – I should point out that I’m not actually an F# guy; in fact I’m pretty new to the language in general so this post is also somewhat of a learning exercise for me. I often find the best way to get acquainted with things is to dive right in, so please feel free to give me pointers in the comments.

Graph based routing itself has been around for a while, in the form of a library called Superscribe (written in C#). I’m not going to go into detail about it’s features; these are language agnostic, and covered by the website and some previous posts.

What I will say is that Superscribe is not a full blown web framework but actually a routing library. In fact, that’s somewhat of an oversimplication… in reality this library takes care of everything between URL and handler. It turns out that routing, content negotiation and some way of invoking a handler is actually all you need to get started building web applications.

Simplicity rules

This simplicity is a key tenet of graph based routing – keeping things minimal helps us build web applications that respond very quickly indeed as there is simply no extra processing going on. If you’re building a very content-heavy application then it’s probably not the right choice, but for APIs it’s incredibly performant.

Lets have a look at an example application using Superscribe in F#:

<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Owin" version="3.0.0" targetFramework="net45" />
<package id="Microsoft.Owin.Host.HttpListener" version="3.0.0" targetFramework="net45" />
<package id="Microsoft.Owin.Host.SystemWeb" version="3.0.0" targetFramework="net45" />
<package id="Microsoft.Owin.Hosting" version="3.0.0" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
<package id="Superscribe" version="0.4.4.15" targetFramework="net45" />
<package id="Superscribe.Owin" version="0.4.3.14" targetFramework="net45" />
</packages>
view raw 1-packages.xml hosted with ❤ by GitHub
namespace Server
open Owin
open Microsoft.Owin
open Superscribe.Owin
open Superscribe.Owin.Engine
open Superscribe.Owin.Extensions;
type Startup() =
member x.Configuration(app: Owin.IAppBuilder) =
let define = OwinRouteEngineFactory.Create();
app.UseSuperscribeRouter(define).UseSuperscribeHandler(define) |> ignore
define.Route("/hello/world", fun _ -> "Hello World" :> obj) |> ignore
define.Route("/hello/fsharp", fun _ -> "Hello from F#!" :> obj) |> ignore
[<assembly: OwinStartup(typeof<Startup>)>]
do ()
view raw 2-startup.fs hosted with ❤ by GitHub
open System
open Microsoft.Owin
[<EntryPoint>]
let main argv =
let baseAddress = "http://localhost:8888";
use a = Hosting.WebApp.Start<Server.Startup>(baseAddress)
Console.WriteLine("Server running on {0}", baseAddress)
Console.ReadLine() |> ignore
0
view raw 3-program.fs hosted with ❤ by GitHub

Superscribe defaults to a text/html response and will try it’s best to deal with whatever object you return from your handler. You can also do all the usual things like specify custom media type serialisers, return status codes etc.

The key part to focus on here is the define.Route statement, which allows us to directly assign a handler to a particular route – in this case /hello/world and /hello/fsharp. This is kinda cool, but there’s a lot more going on here than meets the eye.

Functions and graph based routing

Graph based routing is so named because it stores route definitions in – you guessed it – a graph structure. Traditional route matching tends focus on tables of strings and pattern matching based on the entire URL, but Superscribe is different.

In the example above the URL /hello/world gets broken down into it’s respective segments. Each segment is represented by a node in the graph, with the next possible matches as it’s children. Subsequent definitions are also broken down and intelligently added into the graph, so in this instance we end up with something like this:

hello world graph

Route matching is performed by walking the graph and checking for matches – it’s essentially a state machine. This is great because we only need to check for the segments that we expect; we don’t waste time churning through a large route table.

But here’s where it gets interesting. Nodes in graph based routing are comprised of three functions:

  • Activation function – returns a boolean indicating if the node is a match for the current segment
  • Action function – executed when a match has been found, so we can do things like parameter capture
  • Final function – executed when matching finishes on a particular node, i.e the handler

All of these functions can execute absolutely any arbitrary code that we like. With this model we can do some really interesting things such as conditional route matching based on the time of day, a debug flag or even based on live information from a load balancer. Can your pattern matcher do that!?

Efficiency, composibility and extensibility

Graph based routing allows us to build complex web applications that are composed of very simple units. A good approach is to use action functions to compose a pipeline a functions which get executed synchronously once route matching is complete (is this beginning to sound familiar?), but it can also be used for processing segments on the fly, for example in capturing parameter capture.

Here’s another example that shows this compositional nature in action. We’re going to define and use new type of node that will match and capture certain strings. Because Superscribe relies on the C# dynamic keyword, I’ve used the ? operator provided by FSharp.Dynamic


type NameBeginningWith(letter) as this =
inherit GraphNode()
do
this.ActivationFunction <- fun data segment -> segment.StartsWith(letter)
this.ActionFunctions.Add(
"set_param_Name",
fun data segment -> data.Parameters?Add("Name", segment));
type Startup() =
member x.Configuration(app: Owin.IAppBuilder) =
let define = OwinRouteEngineFactory.Create();
app.UseSuperscribeRouter(define).UseSuperscribeHandler(define) |> ignore
let hello = ConstantNode("hello")
define.Route(
hello / NameBeginningWith "p",
fun o ->
"Hello " + o?Parameters?Name + ", great first letter!" :> obj) |> ignore
define.Route(
hello / String "Name",
fun o ->
"Hello " + o?Parameters?Name :> obj) |> ignore
[<assembly: OwinStartup(typeof<Startup>)>]
do ()

view raw

composition.fs

hosted with ❤ by GitHub

In the previous example we relied on the library to build a graph for us given a string – here we’re being explicit and constructing our own using the / operator (neat eh?). Our custom node will only activate when the segment starts with the letter “p”, and if it does then it will store that parameter away in a dynamic dictionary so we can use it later.

If the engine doesn’t match on a node, it’ll continue through it’s siblings looking for a match there instead. In our case, anything that doesn’t start with “p” will get picked up by the second route – the String parameter node acts as a catch-all:

hello fsharp
hello pete

Pipelines and OWIN

This gets even more exciting when we bring OWIN into the mix. OWIN allows us to build web applications out of multiple pieces of middleware, distinct orthogonal units that run together in a pipeline.

Usually these are quite linear, but with graph based routing and it’s ability to execute arbitrary code, we can build our pipeline on the fly. In this final example, we’re using two pieces of sample middleware to control access to parts of our web application:


type RequireHttps(next: AppFunc) =
member this.Invoke(environment: IDictionary<string, obj>) : Task =
match environment.["owin.RequestScheme"].ToString() with
| "https" -> (next.Invoke(environment))
| other ->
environment.["owin.ResponseStatusCode"] <- 400 :> obj
environment.["owin.ResponseReasonPhrase"] <- "Connection was not secure" :> obj
Task.FromResult<obj>(null) :> Task
type RequireAuthentication(next: AppFunc) =
member this.Invoke(environment: IDictionary<string, obj>) : Task =
let requestHeaders = environment.["owin.RequestHeaders"] :?> Dictionary<string, string>
match requestHeaders.["Authentication"] with
| "ABC123" -> (next.Invoke(environment))
| other ->
environment.["owin.ResponseStatusCode"] <- 403 :> obj
environment.["owin.ResponseReasonPhrase"] <- "Authentication required" :> obj
Task.FromResult<obj>(null) :> Task
type Startup() =
member x.Configuration(app: Owin.IAppBuilder) =
let define = OwinRouteEngineFactory.Create();
app.UseSuperscribeRouter(define).UseSuperscribeHandler(define) |> ignore
define.Route("admin/token", fun o -> "{ token: ABC123 }" :> obj) |> ignore
define.Route("admin/users", fun o -> "List all users" :> obj) |> ignore
let users = define.Route("users")
define.Route(users / String "UserId", fun o -> "User details for " + o?Parameters?UserId :> obj) |> ignore
define.Pipeline("admin").Use<RequireHttps>() |> ignore
define.Pipeline("admin/users").Use<RequireAuthentication>() |> ignore

view raw

pipelining.fs

hosted with ❤ by GitHub

Superscribe has support for this kind of middleware pipelining built in via the Pipeline method. In this code above we’ve specified that anything under the admin/ route will invoke the RequireHttps middleware, and if we’re doing anything other than requesting a token then we’ll need to provide the correct auth header.Behind the syntactic sugar, Superscribe is simply doing everything using the three types of function that we looked at earlier.

This example is not going to win any awards for security practices but it’s a pretty powerful demonstration of how these functional-inspired practices of composition and pipelining can help us build some really flexible and maintainable web applications. It turns out that there really is a lot more synergy between F# and the web that most people realise!

Summary

Some aspects still leave a little to be desired from the functional perspective – our functions aren’t exactly pure for example. But this is just the beginning of the relationship between F# and Superscribe. Most of the examples in the post have been ported straight from C# and so don’t really make any use of F# language features.

I’m really excited about what can be achieved when we start bringing things like monads and discriminated unions into the mix, it should make for some super-terse syntax. I’d love to hear some thoughts on this from the community… I’m sure we can do better than previous attempts at monadic url routing at any rate!

I hope you enjoyed today’s advent calendar… special thanks go to Scott Wlaschlin for all his technical feedback. I deliberately kept the specifics light here so as not to detract from the message of the post, but you can read more about Superscribe and graph based routing on the Superscribe website

Merry christmas to you all!
Pete

References

http://owin.org/
http://sergeytihon.wordpress.com/2014/11/24/f-advent-calendar-in-english-2014/
http://about.me/sergey.tihon
http://superscribe.org/
http://superscribe.org/graphbasedrouting.html
https://github.com/fsprojects/FSharp.Dynamic
https://gist.github.com/unknownexception/6035260
https://github.com/koistya/fsharp-owin-sample
https://github.com/freya-fs/freya
http://blog.ploeh.dk/2013/08/23/how-to-create-a-pure-f-aspnet-web-api-project/
http://wizardsofsmart.net/samples/working-with-non-compliant-owin-middleware/
http://happstack.com/page/view-page-slug/16/comparison-of-4-approaches-to-implementing-url-routing-combinators-including-the-free-and-operational-monads
https://twitter.com/scottwlaschin

Advertisement

From → F#, Owin, REST, Web API

6 Comments
  1. Nice article! How about if you would like to host your static resources from some other site, and get dynamic content from here, you may end up with some CORS-reference-policy-problems? The best workarounds I’ve found: a) to host static files from Microsoft.Owin.StaticFiles or b) to route those through OWIN-pipeline to Azure Blob container like this: https://github.com/Thorium/CatVsDog/blob/master/OwinWorkerRole/Startup.fs

Trackbacks & Pingbacks

  1. F# Advent Calendar in English 2014 | Sergey Tihon's Blog
  2. Dew Drop – December 26, 2014 (#1922) | Morning Dew
  3. F# Weekly #52, 2014 – New Year Edition | Sergey Tihon's Blog
  4. The Morning Brew - Chris Alcock » The Morning Brew #1767
  5. Les liens de la semaine – Édition #113 | French Coding

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: