Query parameters

Apart from passing arguments in the route itself, we can use the query part of url: $rootUrl/store/browse?genre=Disco. For this section we need to open following module:

App.fs

   4: 
open Suave.RequestErrors

Now, let's create a separate WebPart:

App.fs

   8: 
   9: 
  10: 
  11: 
  12: 
let browse = request (fun r -> match r.queryParam "genre" with | Choice1Of2 genre -> OK (sprintf "Genre: %s" genre) | Choice2Of2 msg -> BAD_REQUEST msg)

request is a function that takes as parameter a function of type HttpRequest -> WebPart. A function which takes as an argument another function is often called "Higher order function".

r in our lambda represents the HttpRequest. It has a queryParam member function of type string -> Choice<string,string>.

Choice is a type that represents a choice between two types. Usually you'll find that the first type of Choice is for happy paths, while second means something went wrong. In our case the first string stands for a value of the query parameter, and the second string stands for error message (parameter with given key was not found in query).

We can make use of pattern matching to distinguish between two possible choices. Pattern matching is yet another really powerful feature, implemented in variety of modern programming languages. For now we can think of it as a switch statement with binding value to an identifier in one go. In addition to that, F# compiler will issue an warning in case we don't provide all possible cases (Choice1Of2 x and Choice2Of2 x here). There's actually much more for pattern matching than that, as we'll discover later.

BAD_REQUEST is a function from Suave library which returns WebPart with 400 Bad Request status code response with given message in its body.

We can summarize the browse WebPart as following: If there is a "genre" parameter in the url query, return 200 OK with the value of the "genre", otherwise return 400 Bad Request with error message.

Now we can compose the browse WebPart with routing WebPart like this:

App.fs

  18: 
path "/store/browse" >=> browse
namespace Suave
module Filters

from Suave
module Operators

from Suave
module RequestErrors

from Suave
module Successful

from Suave
module Web

from Suave
val browse : (HttpContext -> Async<HttpContext option>)

Full name: SuaveMusicStore.browse
val request : apply:(HttpRequest -> HttpContext -> 'a) -> context:HttpContext -> 'a

Full name: Suave.Http.request
val r : HttpRequest
member HttpRequest.queryParam : key:string -> Choice<string,string>
union case Choice.Choice1Of2: 'T1 -> Choice<'T1,'T2>
val genre : string
val OK : body:string -> WebPart

Full name: Suave.Successful.OK
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
union case Choice.Choice2Of2: 'T2 -> Choice<'T1,'T2>
val msg : string
val BAD_REQUEST : body:string -> WebPart

Full name: Suave.RequestErrors.BAD_REQUEST
val webPart : WebPart<HttpContext>

Full name: SuaveMusicStore.webPart
val choose : options:WebPart<'a> list -> WebPart<'a>

Full name: Suave.WebPart.choose
val path : pathAfterDomain:string -> WebPart

Full name: Suave.Filters.path
val pathScan : pf:PrintfFormat<'a,'b,'c,'d,'t> -> h:('t -> WebPart) -> WebPart

Full name: Suave.Filters.pathScan
val id : int
val startWebServer : config:SuaveConfig -> webpart:WebPart -> unit

Full name: Suave.Web.startWebServer
val defaultConfig : SuaveConfig

Full name: Suave.Web.defaultConfig

Show code from this section on GitHub

results matching ""

    No results matching ""