Pimbrouwers Falco Versions Save

A toolkit for building fast and functional-first web applications using F#.

v3.1.0

2 years ago

webHost Builder Improvements

In previous versions, the minimalistic web host builder allowed devs to get running quickly and when needed enabled full customization via the configure custom operation. This meant that anything beyond a toy project, required a fair amount of repetitive boilerplate setup code.

To combat this, several custom operations have been added, which semantically match the relevant area (i.e., add_service for services, use_middleware for middleware). The goal is to avoid the need to engage in a full-fledged configuration, although the configure method still exists which will override all other customizations which also creates a kind backward compatibility.

In addition, many common operations have been explicitly mapped: use_static_files, use_https, use_compression etc.

An example of the new builder in action can be found in the docs or samples.

configuration Builder Added

A thin wrapper around ConfigurationBuilder exposing a clean API for reading configuration values.

open Falco.HostBuilder

[<EntryPoint>]
let main args =    
    let env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")
    
    let config = configuration args {
        add_env
        required_json "appsettings.json"
        optional_json (String.Concat([|"appsettings."; env; ".json"|]))
    }

Utility Additions

  • StringUtils.stringf
  • StringUtils.strSplit
  • CookieCollectionReader
  • Auth.getClaimValue
  • Auth.hasScope

New Request functionality

  • Request.getCookie
  • Request.tryBindCookie
  • Request.streamForm
  • Request.tryBindFormStream

New Request HttpHandler's

  • Request.mapCookie
  • Request.bindCookie
  • Request.ifAuthenticatedWithScope

New Request HttpHandler's for streaming multipart data

Two particular fundamental handlers have been added to the Request module, to support multipart form data streaming for large uploads which Microsoft defines large uploads as anything > 64KB.

  • Request.bindFormStream
  • Request.bindFormStreamSecure
  • Request.mapFormStream
  • Request.mapFormStreamSecure

New Response HttpHandler's

Handlers have been added to support binary responses, both inline and attachment. Both asynchronously buffer data into the response body.

  • Response.ofBinary
  • Response.ofAttachment

v3.0.0

3 years ago

With .NET 5.0 finally here, it seemed like a good time to move to v3.x.x which will support both the netcoreapp3.1 and net5.0 build targets. The major version upgraded represented an opportunity to re-evaulate certain features of the API and determine if there were any missed opportunties.

The most practical upgrade was surrounding IHost creating, for which a computation expression has been included: webHost args { ... }. With that came registration & activation extension methods for IServiceCollection and IApplicationBuilder respectively. They are aptly named services.AddFalco() and app.UseFalco(endpoints). The global exception handler hook has been renamed app.UseFalcoExceptionHandler(...).

How you interact with header and route values, now directly matches interactions with queries and forms, all enabled by the StringCollectionReader. A third set of methods was added to this class supporting "get or default" functionality.

Please note, that the ? dynamic operator has been removed.

Listed below is the full list of additions and removals:

Additions

  • IServiceCollection.AddFalco
  • IServiceCollection.AddFalco (routeOptions : RouteOptions -> unit)
  • IApplicationBuilder.UseFalco (endpoints : HttpEndpoint list)
  • IApplicationBuilder.UseFalcoExceptionHandler (exceptionHandler : HttpHandler)
  • QueryCollectionReader replacing direct usage of StringCollectionReader
  • HeaderCollectionReader
  • RouteCollectionReader

Removals

Extensions

  • HttpRequest.GetHeader
  • HttpRequest.GetRouteValues
    • HttpRequest.GetRouteReader

Exceptions

  • type ExceptionHandler
  • type ExceptionHandlingMiddleware

Host module

  • Host.defaultExceptionHandler
  • Host.defaultNotFoundHandler
  • Host.startWebHostDefault
  • Host.startWebHost
  • IApplicationBuilder.UseHttpEndpoints (endpoints : HttpEndpoint list)
    • replaced by IApplicationBuilder.UseFalco (endpoints : HttpEndpoint list)

Request module

  • Request.getHeader
  • Request.getRouteValues
    • replace by Request.getRoute
  • Request.tryGetRouteValue

StringCollectionReader

  • ? dynamic operator

v3.0.0-alpha1

3 years ago

Release Notes

  • Target .NET 5
  • Map alternatives for request IO (route, query, form) for non-exceptional cases, in the form of Request.mapXXX. Applies to all IO forms except JSON.
  • Customizable HTML5 template.

Nuget: https://www.nuget.org/packages/Falco/3.0.0-alpha1

v2.0.3

3 years ago

Release Notes

  • Explicit dependency on TaskBuilder.fs with bolt-on Run member to ensure that automatic Task<unit> -> Task still occurs.

v2.0.0

3 years ago

Release Notes

  • The markup DSL is qualified instead of bare functions.
    • Html.h1 vs h1
    • Attr.class' vs _class
  • Handlers considered end-to-end processors of a request.
    • Continuations are still possible by creating new HttpHandler function which accept another HttpHandler as a parameter.
    • As a result of this change, performance has increased.
  • Host setup functions have been added.
    • These functions (startWebHost and startWebHostDefault) simplify IHost creation.
  • Modular interop with the HttpContext.
    • Optional online extension methods are used to enrich the base library. This functionality is now exposed in a modular fashion (i.e. Response.withStatusCode vs ctx.SetStatusCode).
      • HttpContext based modules exist for: Request, Response, Auth & Xss

Migration Guide

This is a general guide on migrating v1.x.x code to v2.0.0. Both sample apps have been updated and serve as more complete references.

  • The definition of an HttpHandler (HttpContext -> Task) now resembles that of a native RequestDelegate
  • A new definition for any non-IO based modifications to the HttpResponse, called HttpResponseModifier with a definition of HttpContext -> HttpContext
  • Dealing with either the HttpRequest or HttpResponse is now achieved through the Request and Response modules respectively.

An example:

// v1.x.x
let notFound : HttpHandler =
    setStatusCode 404
    >=> textOut "Not Found"

// v2.0.0
let notFound : HttpHandler =
    Response.withStatusCode 404
    >> Response.ofPlainText "Not found"

Another example:

// v.1.x.x
let helloHandler : HttpHandler =
    fun next ctx ->        
        let greeting =
            ctx.tryGetRouteValue "name"
            |> Option.defaultValue "someone"
            |> sprintf "hi %s" 

        textOut

// v2.0.0
let helloHandler : HttpHandler =
    fun ctx ->        
        let greeting =
            Request.tryGetRouteValue "name" ctx 
            |> Option.defaultValue "someone"
            |> sprintf "hi %s" 

        Response.ofPlainText greeting ctx

Another example:

// v1.x.x
let exampleTryBindFormHandler : HttpHandler =
    tryBindForm 
        (fun r ->
            Ok {
              FirstName = form?FirstName.AsString()
              LastName  = form?LastName.AsString()
              Age       = form?Age.AsInt16()      
            })
        errorHandler 
        successHandler

// v2.0.0
let exampleTryBindFormHandler : HttpHandler =
    fun ctx ->
        let bindForm form =     
            {
              FirstName = form?FirstName.AsString()
              LastName  = form?LastName.AsString()
              Age       = form?Age.AsInt16()      
            }

        let respondWith =
            match Request.tryBindForm (bindForm >> Result.Ok) ctx with
            | Error error -> Response.ofPlainText error
            | Ok model    -> Response.ofPlainText (sprintf "%A" model)

        respondWith ctx

Markup

  • Falco.ViewEngine becomes Falco.Markup
  • Element level items now reside in a module called Elem. Thus div becomes Elem.div
    • ** You can import Falco.Markup.Elem and use without Elem. prefix
  • Element attributes are now reside in a module calls Attr. This _class becomes Attr.class'
    • ** Take note of the trailing apostrophe, which is used to delimit reserved keywords like class
  • Text elements now reside in a module called Text. Thus raw becomes Text.raw
    • ** You can import Falco.Markup.Text and use without Text. prefix

An example:

// v1.x.x
let doc = 
    html [] [
            head [] [            
                    title [] [ raw "Sample App" ]                                                    
                ]
            body [] [                     
                    h1 [] [ raw "Sample App" ]
                ]
        ] 

// v2.0.0
let doc = 
    Elem.html [ Attr.lang "en" ] [
            Elem.head [] [                    
                    Elem.title [] [ Text.raw "Sample App" ]                                                            
                ]
            Elem.body [] [                     
                    Elem.main [] [
                            Elem.h1 [] [ Text.raw "Sample App" ]
                        ]
                ]
        ] 

v2.0.0-alpha

3 years ago

Enhancements from v1.x.x:

  • The markup DSL is qualified instead of bare functions.
    • Html.h1 vs h1
    • Attr.class' vs _class
  • Handlers considered end-to-end processors of a request.
    • Continuations are still possible by creating new HttpHandler function which accept another HttpHandler as a parameter.
    • As a result of this change, performance has increased.
  • Host setup functions have been added.
    • These functions (startWebHost and startWebHostDefault) simplify IHost creation.
  • Modular interop with the HttpContext.
    • Optional online extension methods are used to enrich the base library. This functionality is now exposed in a modular fashion (i.e. Response.withStatusCode vs ctx.SetStatusCode).
      • HttpContext based modules exist for: Request, Response, Auth & Xss

v1.2.3

3 years ago
  • HTML View Engine performance improvements.
  • XML Doc updates.

v1.2.2

3 years ago
  • Built-in Task Builder, forked from rspeele's TaskBuilder.fs

v1.2.1

3 years ago

v1.2.0

3 years ago

Enhancements:

  • HttpContext extension method to obtain current user as ClaimsPrincipal option
  • HttpContext extension method to generate and return AntiforgeryTokenSet
  • Built-in handler, authCsrfHtmlOut, which threads both ClaimsPrincipal and AntiforgeryTokenSet through a provided custom HttpHandler
  • UseExceptionMiddlewate extension method on IApplicationBuilder to enable Falco exception handling

Removals:

  • webApp { ... } computation expression (see issue #21 for discussion, and #22 for details)