Build a Simple Single-File Web API with F# / Giraffe
Date: 2024-09-23 | create | tech | fsharp | giraffe | dotnet | webapp |
In this post we're going to build a minimal single-file web API using F# / Giraffe.
This will serve as a good entrypoint into how F# / Giraffe works and can be used as a basis for building your own web apps with F#.
F# / Giraffe Overview
Giraffe is a functional-first micro web framework that plays nice with F#'s functional-first nature. It is a thin wrapper on top of dotnet's ASP.NET web framework (most often used with C#) so you get all of its features and reliability without needing to use C#.
We won't go into too much detail about how Giraffe itself works so if you want to learn more, checkout:
- Build a simple F# web API with Giraffe
- Endpoint Routing with F# / Giraffe
- Top F# Backend Web Frameworks in 2023
Single-File F# / Giraffe Web API
Here we're building a very minimal API. It has 4 endpoints:
- GET
/user/INPUT
-> Returns INPUT - GET
/
-> Returns "" - GET
/get-length/INPUT
-> Returns length of INPUT - POST
/user
-> Returns ""
The idea is to give you a basic idea of how to build endpoints rather than showcase all possibilities.
Note: This is the same basic setup that runs F# / Giraffe's web frameworks benchmark candidate (code) (benchmark) (benchmark requirements)
We declare these Giraffe endpoints, their handlers, and plug them into the core ASP.NET web service in our single file - Program.fs
.
Program.fs
open System
open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Hosting
open Microsoft.AspNetCore.Http
open Microsoft.Extensions.DependencyInjection
open Microsoft.Extensions.Hosting
open Microsoft.Extensions.Logging
open Giraffe
open Giraffe.EndpointRouting
// ---------------------------------
// Web app
// ---------------------------------
let getStringLengthHttpHandler
(s: string)
=
handleContext( fun (ctx: HttpContext) ->
task {
let length = s.Length
return! ctx.WriteTextAsync (string length)
}
)
let webApp =
[
GET [
routef "/user/%s" text
route "/" (text "")
routef "/get-length/%s" (
fun s -> getStringLengthHttpHandler s
)
]
POST [
route "/user" (text "")
]
]
// ---------------------------------
// Config and Main
// ---------------------------------
let configureApp (app: IApplicationBuilder) =
app
.UseRouting()
.UseEndpoints(fun e -> e.MapGiraffeEndpoints(webApp))
|> ignore
let configureServices (services: IServiceCollection) =
services.AddRouting() |> ignore
// Add Giraffe dependencies
services.AddGiraffe() |> ignore
Host
.CreateDefaultBuilder()
.ConfigureWebHost(fun webHost ->
webHost
.UseKestrel(fun c -> c.AddServerHeader <- false)
.ConfigureServices(configureServices)
.Configure(configureApp)
|> ignore)
.Build()
.Run()
webApp
- Declares the Giraffe endpoints and their functionalityconfigureApp
- Configures endpoints into the web appconfigureServices
- Tells ASP.NET it needs to use routing and GiraffeHost
- Tells ASP.NET how it should run
For the most part you can use this configuration code as boilerplate as-is. You will need to change this in the future for some edge cases but this is a decent default for most webapps.
In order for this file to be understood and run by dotnet, we need to declare an .fsproj
which basically declares all dependencies and how to build / run the app.
web.fsproj
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<DebugType>portable</DebugType>
<AssemblyName>web</AssemblyName>
<OutputType>Exe</OutputType>
<EnableDefaultContentItems>false</EnableDefaultContentItems>
</PropertyGroup>
<ItemGroup>
<PackageReference Update="FSharp.Core" Version="8.0.*" />
<PackageReference Include="Giraffe" Version="7.0.*" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.fs" />
</ItemGroup>
</Project>
With both of these files present, we can run the app with dotnet run
(assuming you've installed dotnet on your system).
Full Project Source Code (github) is available to HAMINIONs members - along with dozens of other example projects from guides like this one.
Next
That should get you started with F# / Giraffe.
If you're curious what a real-world fullstack F# / Giraffe web app looks like - CloudSeed (my F# project boilerplate) gets you setup with a fullstack webapp in 10 minutes.
If you liked this post you might also like:
Want more like this?
The best / easiest way to support my work is by subscribing for future updates and sharing with your network.