Skip to content

Instantly share code, notes, and snippets.

@kspeakman
Last active March 31, 2021 23:11
Show Gist options
  • Save kspeakman/81654ffb000191489f1778d344d5910f to your computer and use it in GitHub Desktop.
Save kspeakman/81654ffb000191489f1778d344d5910f to your computer and use it in GitHub Desktop.
ASP NET from F#
// F# type alias
type Builder = IApplicationBuilder -> IApplicationBuilder
let createWebServer settings =
let createBuilder () = (WebHostBuilder(), [])
let setConfig basePath (host: IWebHostBuilder, configs: Builder list) =
( host
.ConfigureAppConfiguration(fun (_: WebHostBuilderContext) (builder: IConfigurationBuilder) ->
builder
.SetBasePath(basePath)
.Build()
|> ignore
)
, configs
)
let setJwtAuth (host: IWebHostBuilder, configs: Builder list) =
// disable default legacy claim mapping for WS-*
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear()
JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear()
( host
.ConfigureServices(fun (context: WebHostBuilderContext) (services: IServiceCollection) ->
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(fun options ->
// cognito does not provide audience claim
options.TokenValidationParameters.ValidateAudience <- false
options.Authority <- settings.CognitoAuthority
)
|> ignore
)
, configs @ [ fun builder -> builder.UseAuthentication() ]
)
let setLogger (host: IWebHostBuilder, configs: Builder list) =
( host
.ConfigureLogging(fun (context: WebHostBuilderContext) (builder: ILoggingBuilder) ->
builder.AddSerilog(seriLogger, true)
|> ignore
)
, configs
)
let setKestrel (host: IWebHostBuilder, configs: Builder list) =
( host
.UseKestrel(fun (context: WebHostBuilderContext) options ->
options.AddServerHeader <- false
host.UseUrls(settings.ApiHostUrls) |> ignore
//options.Configure(context.Configuration.GetSection("Kestrel")) |> ignore
)
, configs
)
let corsRegex = new Regex(settings.CorsPattern, RegexOptions.Compiled)
let setCorsPolicy (host: IWebHostBuilder, configs: Builder list) =
( host
.ConfigureServices(fun (context: WebHostBuilderContext) (services: IServiceCollection) ->
services.AddCors()
|> ignore
)
, configs @ [
fun (app: IApplicationBuilder) ->
app.UseCors(fun (builder: CorsPolicyBuilder) ->
builder
.SetIsOriginAllowed(fun s -> corsRegex.IsMatch(s))
.WithMethods("POST")
// added Cookie and Content-Type for file uploads
.WithHeaders("Authorization", "Cookie", "Content-Type", Messages.Const.UserIdHeader)
.AllowCredentials()
|> ignore
)
]
)
let setAppRoute route (host: IWebHostBuilder, configs: Builder list) =
( host
, configs @ [
fun (app: IApplicationBuilder) ->
app.RunFn route
app
]
)
let build (host: IWebHostBuilder, configs: Builder list) =
host
.Configure(fun (app: IApplicationBuilder) ->
configs
|> List.fold (fun x f -> f x) app
|> ignore
)
.Build()
let basePath = System.IO.Directory.GetCurrentDirectory()
createBuilder ()
|> setConfig basePath
|> setLogger
|> setKestrel
|> setJwtAuth
|> setCorsPolicy
|> setAppRoute (App.routes settings logger)
|> build
[<EntryPoint>]
let main argv =
match settingsOpt with
| None ->
()
| Some settings ->
let webServer = createWebServer settings
webServer.Run()
#if DEBUG
printf "Press ENTER to exit"
Console.ReadLine() |> ignore
#endif
0 // return an integer exit code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment