This article is the continuation of the Suave.io introduction that you can find at the following link.
A web application is generally composed of multiple “routes”. A route means a URL that does not necessarily map a physical file. You can use routes to define some URLs that are semantically meaningful to the user.
To keep it simple, routes are basically paths the user takes which are attached to the code that will be triggered when a user reaches the specific route.
Choose different routes
In the last article, we had a basic routing system, like following.
- let webPart =
- choose [
- path "/" >=> (OK "Home")
- path "/about" >=> (OK "About")
- ]
- startWebServer defaultConfig webPart
It's up to you to define your routes according to the needs of your application; a route returns a WebPart as a response. I will stay on simple examples in this article but the same rules apply in complex applications as well.
The choose function has the following signature.
- val choose: WebPart<'a> list -> WebPart<'a>
It takes a list of WebPart options in parameter and returns a single WebPart value corresponding to the route the user selected. Note that the WebPart value in return can be Some (the first one that applies) or None if the requested route does not correspond to any WebPart.
Path is a function that defines a filter corresponding to a matching string. It takes a string as a parameter and returns a WebPart value. Like I said in previous article, >=> is a Suave operator with the following signature
- val ( >=> ): a: 'a -> Async<'b option> ->b: 'b -> Async<'c option> -> 'a -> Async<'c option>
That takes two WebParts and composes the left WebPart to the right WebPart in one WebPart. The WebPart on the left is evaluated and applied only if Some is returned.
Now, let’s add some routes in our list.
- let webPart =
- choose [
- path "/" >=> (OK "Home")
- path "/about" >=> (OK "About")
- path "/articles" >=> (OK "List of articles")
- path "/articles/browse" >=> (OK "Browse articles")
- path "/articles/details" >=> (OK "Content of an article")
- ]
If you launch the web server, you can now navigate to your routes.

For now, the defined routes remain very basic and static. We will see how to allow interactions through URLs, which will help to render our application dynamic.
URL parameters
URL parameters enable the user to use parameters in the request. For example, access a specific article in a blog with the ID. Suave.io integrates typed routes functionality that means we can control arguments for the route in the code. An argument can have any basic type like an integer or a string.
Suave.io brings some formatters to detect the argument types and filter them. It looks like formatters, like in the printf function from the C standard library. For example, to cache an integer, we use %d or we use %s to cache a string.
Let’s integrate this to enable an id in the details route but before that, I would like to introduce the pathScan function. pathScan is similar to path and has the following signature:
- val pathScan: PrintfFormat<'a,'b,'c,'d,'t> -> 't -> WebPart -> WebPart
It takes two parameters,
- The first parameter is statically typed string formatting function
- The second parameter is a function that takes type of the parameter of the formatted string (‘t) and returns a WebPart.
Edit the current path of details of the article, like this,
- pathScan "/articles/details/%d" (fun id -> OK (sprintf "Content of the article with ID: %d" id))




Join the conversation! Your thoughts help the community grow.