5 people like it.
Like the snippet!
Type-safe URL templates for Nancy
The Nancy web framework parses URLs for you, and passes requests under a given URL route and HTTP method to your program. It relies heavily on C# dynamic objects; these don't translate well in F# code, and it's easy to make mistakes that only show up at run time.
Here we define one F# record type for each route, with an attribute that defines the URL, with placeholders for each field in the record. These types implement one generic interface for each HTTP method they support: for GET, PUT and POST, these generic interfaces also specify the types of the HTTP request and response bodies.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
|
[<Url("/hello/{Who}")>]
type Hello = { Who : string }
with interface IRestGet<string>
interface IRestPut<string, unit>
interface IRestDelete
type DemoModule() as t =
inherit NancyModule()
let mutable greetings = Map.empty
do
t.GetT <| fun (hello : Hello) ->
let greeting = defaultArg (Map.tryFind hello.Who greetings) "Hello"
sprintf "%s, %s!" greeting hello.Who
t.PutT <| fun (hello : Hello) (greeting : string) ->
greetings <- Map.add hello.Who greeting greetings
t.DeleteT <| fun (hello : Hello) ->
greetings <- Map.remove hello.Who greetings
|
Multiple items
type Url =
new : unit -> Url + 1 overload
member BasePath : string with get, set
member Clone : unit -> Url
member HostName : string with get, set
member IsSecure : bool
member Path : string with get, set
member Port : Nullable<int> with get, set
member Query : string with get, set
member Scheme : string with get, set
member SiteBase : string
...
Full name: Nancy.Url
--------------------
type UrlAttribute =
inherit Attribute
new : template:string -> UrlAttribute
member Template : string
Full name: Tim.Nancy.Generic.UrlAttribute
--------------------
Url() : unit
Url(url: string) : unit
--------------------
new : template:string -> UrlAttribute
type Hello =
{Who: string;}
interface IRestDelete
interface IRestPut<string,unit>
interface IRestGet<string>
Full name: Tim.Nancy.Generic.Hello
Hello.Who: string
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = String
Full name: Microsoft.FSharp.Core.string
--------------------
type string<'Measure> = string
Full name: Tim.Nancy.Generic.string<_>
type IRestGet<'Response> =
interface
inherit IRestResource
end
Full name: Tim.Nancy.Generic.IRestGet<_>
type IRestPut<'Request,'Response> =
interface
inherit IRestResource
end
Full name: Tim.Nancy.Generic.IRestPut<_,_>
type unit = Unit
Full name: Microsoft.FSharp.Core.unit
type IRestDelete =
interface
inherit IRestResource
end
Full name: Tim.Nancy.Generic.IRestDelete
Multiple items
type DemoModule =
inherit NancyModule
new : unit -> DemoModule
Full name: Tim.Nancy.Generic.DemoModule
--------------------
new : unit -> DemoModule
val t : DemoModule
Multiple items
type NancyModule =
member After : AfterPipeline with get, set
member Before : BeforePipeline with get, set
member Context : NancyContext with get, set
member Delete : RouteBuilder
member Get : RouteBuilder
member Head : RouteBuilder
member ModelBinderLocator : IModelBinderLocator with get, set
member ModelValidationResult : ModelValidationResult with get, set
member ModulePath : string with get, set
member Negotiate : Negotiator
...
nested type RouteBuilder
Full name: Nancy.NancyModule
--------------------
NancyModule() : unit
NancyModule(modulePath: string) : unit
val mutable greetings : Map<string,string>
Multiple items
module Map
from Microsoft.FSharp.Collections
--------------------
type Map<'Key,'Value (requires comparison)> =
interface IEnumerable
interface IComparable
interface IEnumerable<KeyValuePair<'Key,'Value>>
interface ICollection<KeyValuePair<'Key,'Value>>
interface IDictionary<'Key,'Value>
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
member Add : key:'Key * value:'Value -> Map<'Key,'Value>
member ContainsKey : key:'Key -> bool
override Equals : obj -> bool
member Remove : key:'Key -> Map<'Key,'Value>
...
Full name: Microsoft.FSharp.Collections.Map<_,_>
--------------------
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
val empty<'Key,'T (requires comparison)> : Map<'Key,'T> (requires comparison)
Full name: Microsoft.FSharp.Collections.Map.empty
member NancyModule.GetT : fn:(#IRestGet<'Response> -> 'Response) -> unit
val hello : Hello
val greeting : string
val defaultArg : arg:'T option -> defaultValue:'T -> 'T
Full name: Microsoft.FSharp.Core.Operators.defaultArg
val tryFind : key:'Key -> table:Map<'Key,'T> -> 'T option (requires comparison)
Full name: Microsoft.FSharp.Collections.Map.tryFind
val sprintf : format:Printf.StringFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
member NancyModule.PutT : fn:(#IRestPut<'Request,'Response> -> 'Request -> 'Response) -> unit
val add : key:'Key -> value:'T -> table:Map<'Key,'T> -> Map<'Key,'T> (requires comparison)
Full name: Microsoft.FSharp.Collections.Map.add
member NancyModule.DeleteT : fn:(#IRestDelete -> unit) -> unit
val remove : key:'Key -> table:Map<'Key,'T> -> Map<'Key,'T> (requires comparison)
Full name: Microsoft.FSharp.Collections.Map.remove
More information