Wednesday, April 22, 2015

A Simple Nowin F# Example

In my last post I showed a simple F# OWIN self hosted server without an application framework. Today I want to show an even simpler example that doesn’t reference any of the Microsoft OWIN libraries, but instead uses an open source server implementation, Nowin. Thanks to Damien Hickey for pointing me in the right direction.

The great thing about the Open Web Interface for .NET (OWIN) is that it is simply a specification. There is no OWIN library that you have to install to allow web servers, application frameworks and middlewear built to the OWIN standard to communicate. There is no interface that they must implement. They simply need to provide an entry point for the OWIN application delegate (better know as the AppFunc):

    Func<IDictionary<string , object>, Task>

For simple applications, where we don’t need routing, authentication, serialization, or an application framework, this means we can simply provide our own implementation of the AppFunc and pass it directly to an OWIN web server.

Nowin, by Boris Letocha, is a .NET web server, built directly against the standard .NET socket API. This means it should work on all platforms that support .NET without modification. The author claims that it has equivalent performance to NodeJS on Windows and can even match HttpListener. Although not ready for production, it makes a compelling implementation for simple test servers and stubs, which is how I intend to use it.

To use any OWIN web server with F#, we simply need to provide an AppFunc and since F# lambdas have an implicit cast to System.Func<..> we can simply provide the AppFunc in the form:

    fun (env: IDictionary<string, obj>) -> Task.FromResult(null) :> Task

Let’s see it in action. First create an F# console application and install the Nowin server with NuGet:

    Install-Package Nowin

Now we can host our Nowin server in the application’s entry point:

    let main argv = 

        use server = 
                .SetEndPoint(new IPEndPoint(IPAddress.Any, port))
                .SetOwinApp(fun env -> Task.FromResult(null) :> Task)


        printfn "Server listening on http://localhost:%i/ \nhit <enter> to stop." port
        Console.ReadLine() |> ignore


Of course this server does nothing at all. It simply returns the default 200 OK response with no body. To do any useful work you need to read the OWIN environment, understand the request and create a response. To make this easier in F# I’ve created a simple OwinEnvironment type with just the properties I need. You could expand this to encompass whatever OWIN environment properties you need. Just look at the OWIN spec for this.

    type OwinEnvironment = {
        httpMethod: string;
        requestBody: Stream;
        responseBody: Stream;
        setResponseStatusCode: (int -> unit);
        setResponseReasonPhrase: (string -> unit)

Here is a function that takes the AppFunc environment and maps it to my OwinEnvironment type:

    let getOwinEnvironment (env: IDictionary<string , obj>) = {
        httpMethod = env.["owin.RequestMethod"] :?> string;
        requestBody = env.["owin.RequestBody"] :?> Stream;
        responseBody = env.["owin.ResponseBody"] :?> Stream;
        setResponseStatusCode = 
            fun (statusCode: int) -> env.["owin.ResponseStatusCode"] <- statusCode
        setResponseReasonPhrase = 
            fun (reasonPhrase: string) -> env.["owin.ResponseReasonPhrase"] <- reasonPhrase

Now that we have our strongly typed OwinEnvironment, we can grab the request stream and response stream and do some kind of mapping. Here is a function that does this. It also only accepts POST requests, but you could do whatever you like in the body. Note the transform function is where the work is done.

    let handleOwinEnvironment (owin: OwinEnvironment) : unit =
        use writer = new StreamWriter(owin.responseBody)
        match owin.httpMethod with
        | "POST" ->
            use reader = new StreamReader(owin.requestBody)
        | _ ->
            owin.setResponseStatusCode 400
            owin.setResponseReasonPhrase "Bad Request"
            writer.Write("Only POST requests are allowed")

Just for completeness, here is a trivial transform example:

    let transform (request: string) : string =
        sprintf "%s transformed" request

Now we can re-visit our console Main function and pipe everything together:

    let main argv = 

        use server = 
                .SetEndPoint(new IPEndPoint(IPAddress.Any, port))
                .SetOwinApp(fun env -> 
                    |> getOwinEnvironment 
                    |> handleOwinEnvironment 
                    |> endWithCompletedTask)


        printfn "Server listening on http://localhost:%i/ \nhit  to stop." port
        Console.ReadLine() |> ignore


The endWithCompletedTask function, is a little convenience to hide the ugly synchronous Task return code:

    let endWithCompletedTask = fun x -> Task.FromResult(null) :> Task

So as you can see, OWIN and Nowin make it very easy to create small web servers with F#. Next time you just need a simple service stub or test server, consider doing something like this, rather that using a heavyweight server and application framework such as IIS, MVC, WebAPI or WebForms.

You can find the complete code for the example in this Gist

Thursday, April 16, 2015

Basic OWIN Self Host With F#

I’m still very much an F# noob, but yesterday I thought I’d use it to write a little stub web service for a project I’m currently working on. I simply want to respond to any POST request to my service. I don’t need routing, or any other ‘web framework’ pieces. I just wanted to use the Microsoft.AspNet.WebApi.OwinSelfHost package to create a little web service that runs inside a console program.

First create a new F# console project. Then install the self host package:


Note that this will also install various WebApi pieces which we don’t need here, so we can go ahead and uninstall them:

    uninstall-package Microsoft.AspNet.WebApi.OwinSelfHost
    uninstall-package Microsoft.AspNet.WebApi.Owin
    uninstall-package Microsoft.AspNet.WebApi.Core
    uninstall-package Microsoft.AspNet.WebApi.Client

My requirement is to simply take any POST request to the service, take the post body and transform it in some way (that’s not important here), and then return the result in the response body.

So first, here’s a function that takes a string and returns a string:

    let transform (input: string) =
        sprintf "%s transformed" input

Next we’ll write the OWIN start-up class. This needs to be a class with a single member, Configuration, that takes an IAppBuilder:

    open Owin
    open Microsoft.Owin
    open System
    open System.IO
    open System.Threading.Tasks

    type public Startup() = 
        member x.Configuration (app:IAppBuilder) = app.Use( ... ) |> ignore

We need something to pass into the Use method on IAppBuilder. The Use method looks like this:

    public static IAppBuilder Use(
        this IAppBuilder app,
        Func<IOwinContext, Func<Task>, Task> handler

So we need a handler with the signature Func<IOwinContext, Func<Task>, Task>. Since F# lambdas cast directly to Func<..> delegates, we simply use lots of type annotations and write a function which looks like this:

    let owinHandler = fun (context:IOwinContext) (_:Func) -> 
        handleOwinContext context; 
        Task.FromResult(null) :> Task

Note that this is running synchronously. We’re just returning a completed task.

Now lets look at the handleOwinContext function. This simply takes the IOwinContext, grabs the request, checks that it’s a ‘POST’, and transforms the request stream into the response stream using our transform function:

    let handleOwinContext (context:IOwinContext) =

        use writer = new StreamWriter(context.Response.Body)

        match context.Request.Method with
        | "POST" -> 
            use reader = new StreamReader(context.Request.Body)
        | _ ->
            context.Response.StatusCode <- 400
            writer.Write("Only POST")

Now all we need to do is register our Startup type with the OWIN self host in our Program.Main function:

open System
open Microsoft.Owin.Hosting

let main argv = 

    let baseAddress = "http://localhost:8888"

    use application = WebApp.Start<Startup.Startup>(baseAddress)

    Console.WriteLine("Server running on {0}", baseAddress)
    Console.WriteLine("hit <enter> to stop")
    Console.ReadLine() |> ignore

And we’re done. Now let’s try it out with the excellent Postman client, just run the console app and send a POST request to http://localhost:8888/:


Full source code in this Gist.