Host Configuration
The webHost[||] { ... }
computation aims to provide a consistent methodology for creating .NET servers using Kestrel. It's performant, secure, and maintained by the incredibly smart people on the ASP.NET Team at Microsoft.
Config, Logging & Other Operations
Operation | Description |
---|---|
host | Configure the host via IHostBuilder . |
web_host | Configure the host via IHostBuilder . |
logging | Configure logging via ILoggingBuilder . |
not_found | Include a catch-all (i.e., Not Found) HttpHandler (must be added last). |
host
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.Extensions.Hosting
open Serilog
let configureHost (host : IHostBuilder) =
host.AddSerilog()
host
webHost [||] {
host configureHost
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
web_host
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.Extensions.Hosting
open Serilog
let configureWebHost (webHost : IWebHostBuilder) =
webHost.UseHttpSys()
webHost
webHost [||] {
web_host configureWebHost
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
logging
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
open Microsoft.Extensions.Logging
let configureLogging (log : ILoggingBuilder) =
log.ClearProviders()
log.AddConsole()
log
webHost [||] {
logging configureLogging
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
not_found
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
module ErrorPages =
let unauthorized : HttpHandler =
Response.withStatusCode 404
>> Response.ofPlainText "Not Found"
webHost [||] {
not_found ErrorPages.notFound
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
Registering Services
Operation | Description |
---|---|
add_service | Add a new service descriptor into the IServiceCollection. |
add_antiforgery | Add Antiforgery support into the IServiceCollection . |
add_cookie | Add configured cookie into the IServiceCollection . |
add_cookies | Add configured cookie collection into the IServiceCollection . |
add_authorization | Add default Authorization into the IServiceCollection . |
add_data_protection | Add file system based data protection. |
add_http_client | Add IHttpClientFactory into the IServiceCollection |
add_antiforgery
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
webHost [||] {
add_antiforgery
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
add_cookie
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
let cookieScheme = "MyAppScheme"
webHost [||] {
add_cookie cookieScheme
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
add_cookies
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Authentication
open Microsoft.AspNetCore.Authentication.Cookies
open Microsoft.AspNetCore.Builder
let cookieScheme = "MyApp"
let authConfig
(scheme : string)
(options : AuthenticationOptions) =
options.DefaultScheme <- scheme
let cookieConfig
let cookieOptions
(scheme : string)
(options : CookieAuthenticationOptions) =
options.AccessDeniedPath <- "/account/denied"
options.LoginPath <- "/account/login"
options.Cookie.Path <- "/"
options.Cookie.HttpOnly <- true
options.Cookie.SameSite <- SameSiteMode.Strict
options.Cookie.SecurePolicy <- CookieSecurePolicy.Always
[ cookieScheme, cookieOptions cookieScheme ]
webHost [||] {
endpoints [
add_cookies authConfig cookieConfig
get "/" (Response.ofPlainText "Hello world")
]
}
add_authorization
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
webHost [||] {
add_authorization
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
add_data_protection
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
webHost [||] {
add_data_protection "C:\\Data\\Protection\\Dir"
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
add_http_client
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
webHost [||] {
add_http_client
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
Activating Middleware
Operation | Description |
---|---|
use_middleware | Use the specified middleware. |
use_if | Use the specified middleware if the provided predicate is "true". |
use_ifnot | Use the specified middleware if the provided predicate is "true". |
use_authentication | Use authorization middleware. Call before any middleware that depends on users being authenticated. |
use_authorization | Register authorization service and enable middleware |
use_caching | Register HTTP Response caching service and enable middleware. |
use_compression | Register Brotli + GZip HTTP Compression service and enable middleware. |
use_hsts | Use automatic HSTS middleware (adds strict-transport-policy header). |
use_https | Use automatic HTTPS redirection. |
use_cors | Set CORS (Cross Origin Resource Sharing) options and policy. |
use_default_files | Use Default Files middleware. |
use_static_files | Use Static Files middleware. |
use_if
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
webHost [||] {
use_if FalcoExtensions.IsDevelopment DeveloperExceptionPageExtensions.UseDeveloperExceptionPage
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
use_ifnot
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
webHost [||] {
use_ifnot FalcoExtensions.IsDevelopment HstsBuilderExtensions.UseHsts
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
use_authentication
Note: this must be called before
use_authorization
, and called afteruse_hsts
,use_http
,use_compression
,use_static_files
.
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
webHost [||] {
use_authentication
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
use_authorization
Note: this must be called after
use_authentication
.
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
webHost [||] {
use_authorization
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
use_caching
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
webHost [||] {
use_caching
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
use_compression
Note: this should be called before
use_static_files
if compression is desired on static assets.
In addition to the default MIME types, this enables compression for the following: image/jpeg
, image/png
, image/svg+xml
, font/woff
, font/woff2'
.
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
webHost [||] {
use_compression
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
use_hsts
Note: this should be called before
use_https
.
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
webHost [||] {
use_hsts
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
use_https
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
webHost [||] {
use_https
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
use_cors
Note: Typically,
use_static_files
is called beforeuse_cors
. But apps that use JavaScript to retrieve static files cross site must calluse_cors
beforeuse_static_files
.
See the official docs for all the options. Only "CORS with named policy and Middleware" is supported.
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Cors.Infrastructure
let corsPolicyName = "MyCorsPolicy"
let corsPolicy (policyBuilder: CorsPolicyBuilder) =
// Note: This is a very lax setting, but a good fit for local development
policyBuilder
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
// Note: The URLs must not end with a /
.WithOrigins("http://localhost:3000",
"http://localhost:5001")
|> ignore
let corsOptions (options : CorsOptions) =
options.AddPolicy(corsPolicyName, corsPolicy)
webHost [||] {
use_cors corsPolicyName corsOptions
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
use_default_files
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
webHost [||] {
use_default_files
use_static_files
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
use_static_files
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
webHost [||] {
use_static_files
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
Custom Services and Middleware
Operation | Description |
---|---|
add_service | Add a new service descriptor into the IServiceCollection. |
use_middleware | Use the specified middleware. |
add_service
Note the use of the
ConfigurationBuiler
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
open Microsoft.Data.Sqlite
type IDbConnectionFactory =
abstract member CreateConnection : unit -> IDbConnection
let connectToDb : HttpHandler =
Services.inject<IDbConnectionFactory>(fun db ->
use conn = db.CreateConnection()
// code which uses IDbConnection...
)
type DbConnectionFactory (connectionString : string) =
interface IDbConnectionFactory with
member _.CreateConnection () =
let conn = new SqliteConnection(connectionString)
conn.TryOpenConnection()
conn
[<EntryPoint>]
let main args =
// Using the ConfigurationBuilder
let config = configuration [||] {
required_json "appsettings.json"
}
// Register our database connection factory service
let dbConnectionService (svc : IServiceCollection) =
svc.AddSingleton<IDbConnectionFactory, DbConnectionFactory>(fun _ ->
// Load default connection string from appsettings.json
let connectionString = config.GetConnectionString("Default")
new DbConnectionFactory(connectionString))
webHost [||] {
endpoints [
get "/" (Response.ofPlainText "Hello world")
]
}
0
use_middleware
open System.Globalization
open System.Threading.Tasks
open Falco
open Falco.Routing
open Falco.HostBuilder
open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Http
let displayCulture : HttpHandler = fun ctx ->
Response.ofPlainText CultureInfo.CurrentCulture.DisplayName ctx
let cultureMiddleware (app : IApplicationBuilder) =
let middleware (ctx : HttpContext) (next : RequestDelegate) : Task =
task {
let query = QueryCollectionReader(ctx.Request.Query)
match query.TryGet "culture" with
| Some cultureQuery ->
let culture = CultureInfo(cultureQuery)
CultureInfo.CurrentCulture <- culture
CultureInfo.CurrentUICulture <- culture
| None -> ()
return! next.Invoke(ctx)
}
app.Use(middleware)
webHost [||] {
use_middleware cultureMiddleware
endpoints [
any "/" displayCulture
]
}