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:
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.
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:
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.
My script file resides in a sub folder of the actually server code, hence the “../../”.
I then can create the actual server.
This code handles the retrieval of the request:
This code handles the processing of the request and the generation of the response:
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:
Finally I have to create and be able to start and stop the webserver.
Now I can write some code to test my setup:
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.