Testing a Saturn Web App

The first thing I will trying when using a new framework or library is to start writing code in a script file and see what happens in the interactive. Normally, I am just to stupid to understand the guidelines, but by experimenting and finding it out myself by writing code I manage to get my head around the new framework or library I am using.

The same applies when I tried to get a web app running using Saturn. Previously, I used Suave and then Giraffe as primary web server solutions. Saturn is actually, yet another shell around the ASP.NET core framework, actually Giraffe wraps ASP.NET Core and Saturn wraps Giraffe. So, I had some previous experience with similar frameworks. Still, getting a web app up and running handling requests is a daunting task (to me it is).

Requests and Responses

The whole notion of a web app is that there is a client that fires requests at a server, which responds with … responds. In order to keep things simple I want my webserver to have one channel for dynamic requests: api/request, using a POST method to post the actual request. Upon which the server responds with an option response (things can go wrong). I therefore have the following:

HTML

First of all the code is shared, so the request type can be used by both the client and the server (using the SAFE-stack setup). Thus the client can sent a request the server also understands. Secondly I wrap the actually request in the request type. This enables me to have one type that represents patient requests or configuration requests, etc… The whole thing looks like a:

Request –> Response function

Next the response looks very similar.

HTML

Again the code is shared by server and client, so the server can create a response the client understands. And now I want to start playing around with this concept.

Running the code in a script file

The first thing you need to do is to run the code in a script file. In a previous post I described how to load all the required libraries in the script file. The caveat being that sometimes the referenced libraries are in the wrong order. The same applies here, so I had to manually move the following libs down to the end of the load script file:

HTML

I also make sure that the path is set to the current source code path so relative paths can be resolved to the correct absolute paths.

HTML

My script file resides in a sub folder of the actually server code, hence the “../../”.

I then can create the actual server.

HTML

This code handles the retrieval of the request:

HTML

This code handles the processing of the request and the generation of the response:

HTML

Fairly simple isn’t it. But then I want to start playing around with this setup. Therefore, I need to start the server as a separate process and be able to stop the server once I am done. Simply running: run Server.app, as normal won’t work because then the server is running in process and I cannot start ‘talking’ to the server by running code in the FSI.

Starting up and stopping a web server in a separate thread

Luckily, F# has an elegant solution to enable code to run in a separate process called MailboxProcessors. So, you can start the webserver in a MailboxProcessor, or Agent and then run code to use the webserver. The one thing is that if you stop the MailboxProcessor, the webserver still keeps running until you restart the FSI. Therefore, you need to start the webserver with a CancellationToken, like:

HTML

Finally I have to create and be able to start and stop the webserver.

HTML

Now I can write some code to test my setup:

HTML

The one thing that is not working (yet) is the ability to restart the server. Once it is stop, you need to reset the FSI and reload again. So, if anybody has a solution? Meanwhile this is a perfect way to play with a webserver.

Leave a Reply

Your email address will not be published. Required fields are marked *