Fleece


Suave

In this page we will get an overview of how you can use Fleece together with Suave.

A minimal integration can be done by

open Suave
open Suave.Http
open Suave.Operators
open System.IO
open System.Text
// Fleece and Json related:
open System.Json
open Fleece.SystemJson
open Fleece.SystemJson.Operators

module BusinessApp=
    [<RequireQualifiedAccess>]
    module Json =
        let inline OK (dataObj) : WebPart=
            let str = toJson dataObj |> string
            Successful.OK str
            >=> Writers.setMimeType "application/json; charset=utf-8"

        let inline parseRequestForm (ctx : HttpContext) =
            let body = ctx.request.rawForm |> Encoding.UTF8.GetString
            parseJson body

In the web API part of your business app you would then do something like the code below:

open BusinessApp

type Person = { Name : string }
with
    static member JsonObjCodec =
        fun name -> { Name = name }
        <!> jreq  "name" (Some << fun x -> x.Name)

let personHandler : WebPart =
    warbler (fun ctx ->
            match Json.parseRequestForm ctx with // instead of using mapJson
            | Ok (person:Person)->
                Json.OK person
            // and ideally we would deal with case when the parsing fails as well
    )
module Suave
namespace Suave
module Http from Suave
module Operators from Suave
namespace System
namespace System.IO
namespace System.Text
namespace System.Json
namespace Fleece
module SystemJson from Fleece
module Operators from Fleece.SystemJson
Multiple items
type RequireQualifiedAccessAttribute = inherit Attribute new : unit -> RequireQualifiedAccessAttribute
<summary>This attribute is used to indicate that references to the elements of a module, record or union type require explicit qualified access.</summary>
<category>Attributes</category>


--------------------
new : unit -> RequireQualifiedAccessAttribute
Multiple items
module Json from Suave.BusinessApp

--------------------
namespace System.Text.Json

--------------------
module Json from Suave
val OK : dataObj:'a -> WebPart (requires member ToJson)
val dataObj : 'a (requires member ToJson)
Multiple items
module WebPart from Suave

--------------------
type WebPart = WebPart<HttpContext>

--------------------
type WebPart<'a> = 'a -> Async<'a option>
<summary> Takes 'a and returns SuaveTask of 'a SuaveTask is also known as AsyncOption </summary>
val str : string
val toJson : x:'t -> JsonValue (requires member ToJson)
<summary> Maps a value to Json </summary>
Multiple items
val string : value:'T -> string
<summary>Converts the argument to a string using <c>ToString</c>.</summary>
<remarks>For standard integer and floating point values the and any type that implements <c>IFormattable</c><c>ToString</c> conversion uses <c>CultureInfo.InvariantCulture</c>. </remarks>
<param name="value">The input value.</param>
<returns>The converted string.</returns>


--------------------
type string = System.String
<summary>An abbreviation for the CLI type <see cref="T:System.String" />.</summary>
<category>Basic Types</category>
module Successful from Suave
<summary><para> 2xx successful responses </para><para> Functions have signature <code>f :: params... -&gt; HttpContext -&gt; Async&lt;unit&gt; option</code>. </para><para> Functions from here are 'end routes' in that they don't require you to keep returning applicatives, but can end up in an async monad/workflow that writes the data to the client in the end. </para></summary>
val OK : body:string -> WebPart
<summary><para> 200 </para><para> Write the string to the body as UTF-8 </para></summary>
<remarks></remarks>
module Writers from Suave
<summary> Module that allows changing the output response in different ways. Functions have signature f :: params... -&gt; HttpContext -&gt; HttpContext. </summary>
val setMimeType : mimeType:string -> WebPart
<summary><para> Set the Content-Type header to the mime type given. Remember that it should include the encoding of your content. So for example, specifying a mimeType value of 'application/json; charset=utf-8' is strongly recommended (but replace 'json' with your own MIME type, of course ;)) </para><para></para><para></para></summary>
<remarks></remarks>
val parseRequestForm : ctx:HttpContext -> 'a ParseResult (requires member OfJson)
val ctx : HttpContext
Multiple items
module HttpContext from Suave.Http
<summary> A module that provides functions to create a new HttpContext. </summary>

--------------------
type HttpContext = { request: HttpRequest runtime: HttpRuntime connection: Connection userState: Map<string,obj> response: HttpResult } member clientIp : trustProxy:bool -> sources:string list -> IPAddress member clientPort : trustProxy:bool -> sources:string list -> Port member clientProto : trustProxy:bool -> sources:string list -> string member clientIpTrustProxy : IPAddress member clientPortTrustProxy : Port member clientProtoTrustProxy : string member isLocal : bool static member clientIp_ : Property<HttpContext,IPAddress> static member clientPort_ : Property<HttpContext,Port> static member clientProto_ : Property<HttpContext,string> ...
<summary> The HttpContext is the container of the request, runtime, user-state and response. </summary>
val body : string
HttpContext.request: HttpRequest
<summary> The HTTP request being processed </summary>
HttpRequest.rawForm: byte []
type Encoding = interface ICloneable new : unit -> unit + 2 overloads member Clone : unit -> obj member Equals : value: obj -> bool member GetByteCount : chars: nativeptr<char> * count: int -> int + 5 overloads member GetBytes : chars: nativeptr<char> * charCount: int * bytes: nativeptr<byte> * byteCount: int -> int + 7 overloads member GetCharCount : bytes: nativeptr<byte> * count: int -> int + 3 overloads member GetChars : bytes: nativeptr<byte> * byteCount: int * chars: nativeptr<char> * charCount: int -> int + 4 overloads member GetDecoder : unit -> Decoder member GetEncoder : unit -> Encoder ...
<summary>Represents a character encoding.</summary>
property Encoding.UTF8: Encoding with get
<summary>Gets an encoding for the UTF-8 format.</summary>
<returns>An encoding for the UTF-8 format.</returns>
(extension) Encoding.GetString(bytes: inref<System.Buffers.ReadOnlySequence<byte>>) : string
Encoding.GetString(bytes: System.ReadOnlySpan<byte>) : string
Encoding.GetString(bytes: byte []) : string
Encoding.GetString(bytes: nativeptr<byte>, byteCount: int) : string
Encoding.GetString(bytes: byte [], index: int, count: int) : string
val parseJson : x:string -> 'a ParseResult (requires member OfJson)
<summary> Parses a Json Text and maps to a type </summary>
module BusinessApp from Suave
Person.Name: string
val name : string
val jreq : name:string -> getter:('T -> 'param option) -> ConcreteCodec<System.Collections.Generic.KeyValuePair<string,JsonValue> list,System.Collections.Generic.KeyValuePair<string,JsonValue> list,'param,'T> (requires member OfJson and member ToJson)
<summary> Derives a concrete field codec for a required field </summary>
union case Option.Some: Value: 'T -> Option<'T>
<summary>The representation of "Value of type 'T"</summary>
<param name="Value">The input value.</param>
<returns>An option representing the value.</returns>
val x : Person
val personHandler : WebPart
val warbler : f:('t -> 't -> 'u) -> 't -> 'u
<summary> Which bird? A Warbler! Pipe the request through to a bird that can peck at it. Put another way, using 'warbler' lets you look at the first parameter and then make a decision about what thing to return (it's most likely a WebPart you'll be returning). (Remember, WebPart is HttpContext -&gt; Async&lt;HttpContext option&gt;) where HttpContext is 'a and Async&lt;_&gt; is 'b. </summary>
union case Result.Ok: ResultValue: 'T -> Result<'T,'TError>
<summary> Represents an OK or a Successful result. The code succeeded with a value of 'T. </summary>
val person : Person
type Person = { Name: string } static member JsonObjCodec : ConcreteCodec<KeyValuePair<string,JsonValue> list,KeyValuePair<string,JsonValue> list,Person,Person>