Getting Started with Suave
This guide will help you install Suave and create your first web server.
Prerequisites
- .NET 8 or later
- F# 4.7 or later
- A code editor (VS Code, Visual Studio, or similar)
Installation
Step 1: Create a new F# project
dotnet new console -lang F# -n MyWebServer
cd MyWebServer
Step 2: Add Suave via NuGet
dotnet add package Suave
Hello World
Replace the contents of Program.fs with:
open Suave
open Suave.Successful
let app = OK "Hello, Suave!"
startWebServer defaultConfig app
Run your server:
dotnet run
Open your browser to http://localhost:8080 and you should see "Hello, Suave!"
JSON Response
Return a typed record as JSON with Suave.Json.toJson. Install the package first:
dotnet add package Suave.Json
toJson lives in the separate Suave.Json NuGet package — it is not part of core Suave.
open System.Runtime.Serialization
open Suave
open Suave.Operators
open Suave.Writers
open Suave.Json
[<DataContract>]
type Person =
{ [<field: DataMember(Name = "name")>] name : string
[<field: DataMember(Name = "age")>] age : int }
let person = { name = "Alice"; age = 30 }
// toJson : 'T -> byte[] — use Successful.ok (bytes), not OK (string)
let app =
toJson person
|> Successful.ok
>=> setMimeType "application/json"
startWebServer defaultConfig app
For request/response mapping with mapJson, see the JSON recipe.
Basic Routing
Handle different URLs:
open Suave
open Suave.Filters
open Suave.Operators
open Suave.Successful
open Suave.RequestErrors
let app =
choose [
path "/" >=> OK "Welcome!"
path "/about" >=> OK "About page"
path "/contact" >=> OK "Contact us"
NOT_FOUND "Page not found"
]
startWebServer defaultConfig app
Handling Requests
Access request data:
open Suave
open Suave.Filters
open Suave.Operators
let app =
request (fun req ->
let method = req.method
let url = req.url
sprintf "You made a %s request to %s" (string method) (string url)
|> Successful.OK)
startWebServer defaultConfig app
Query Parameters
Parse query strings:
open Suave
open Suave.Filters
open Suave.Operators
open Suave.Successful
let app =
request (fun req ->
match req.queryParam "name" with
| Choice1Of2 name -> OK (sprintf "Hello, %s!" name)
| Choice2Of2 _ -> OK "No name provided")
startWebServer defaultConfig app
Try: http://localhost:8080?name=World
POST Data & Forms
Handle form submissions:
open Suave
open Suave.Filters
open Suave.Operators
open Suave.Successful
let app =
choose [
POST >=> request (fun req ->
match req.formData "message" with
| Choice1Of2 message -> OK (sprintf "Received: %s" message)
| Choice2Of2 _ -> OK "No message")
GET >=> OK """
<form method="POST">
<input name="message">
<button>Send</button>
</form>"""
]
startWebServer defaultConfig app
Serving Static Files
Serve files from a directory:
open Suave
open Suave.Filters
open Suave.Operators
open Suave.Files
let app =
choose [
browseHome
Files.file "404.html"
]
let config = {
defaultConfig with
homeFolder = Some (System.IO.Path.GetFullPath("public"))
}
startWebServer config app
Configuration
Customize your server:
open Suave
open Suave.Successful
let app = OK "Hello"
let config = {
defaultConfig with
bindings = [ HttpBinding.createSimple HTTP "127.0.0.1" 3000 ]
homeFolder = Some "public"
hideHeader = false
}
startWebServer config app
Next Steps
- Learn more about routing patterns
- Understand WebPart composition
- Add WebSocket support
- Serve traffic over HTTP/2
- Check out the examples on GitHub
Troubleshooting
Port already in use
If port 8080 is already in use, change it in the config:
open Suave
open Suave.Successful
let app = OK "Hello"
let config = {
defaultConfig with
bindings = [ HttpBinding.createSimple HTTP "127.0.0.1" 3000 ]
}
startWebServer config app
Changes not showing
Stop the server (Ctrl+C) and rebuild:
dotnet clean
dotnet build
dotnet run