Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a query parameter in F# Saturn Framework?

Say we have this web server to handle requests:

let webApp = scope {
    get  "/api/zoo/animals/"    (getAllAnimals())
    getf "/api/zoo/animals/%s"  getAnimalInfo
}

This syntax is described in docs and demoed in the example.

Now, what if I want to have a param in the url query, e.g. to filter the results?

http://localhost:8080/api/zoo/animals?type=mammals

This does not do anything:

getf "/api/zoo/animals?type=%s" getAnimalsByType
like image 925
psfinaki Avatar asked Jul 14 '18 15:07

psfinaki


People also ask

What is %20 in query string?

According to the W3C (and they are the official source on these things), a space character in the query string (and in the query string only) may be encoded as either " %20 " or " + ".

Which is an example of a query parameter?

Query Parameter Example For example, in `https://www.google.com/search?q=abstract%20api`, we have a standard Google search, with the user input `abstract%20api` being passed as a variable via the query parameter `q=`. We can pass multiple variables with the `&` symbol separating parameters, forming a query string.


2 Answers

See the example here:

https://github.com/giraffe-fsharp/Giraffe/blob/master/DOCUMENTATION.md#query-strings

It shows how to bind the data from a query string so you don't have to use GetQueryStringValue

In your case I think something like this might work.

[<CLIMutable>]
type AnimalType =
    { type : string }

let animal (next : HttpFunc) (ctx : HttpContext) =
    // Binds the query string to a Car object
    let animal = ctx.BindQueryString<AnimalType>()

    // Sends the object back to the client
    Successful.OK animal next ctx

let web_app  =

    router {    
        pipe_through (pipeline { set_header "x-pipeline-type" "Api" })
        post "/api/animal" animal
    }
like image 68
sashang Avatar answered Oct 19 '22 10:10

sashang


A way to go is to use function GetQueryStringValue of the context. It returns Result, a struct DU.

So you stay with initial signature (just remove the trailing slash):

get "/api/zoo/animals" (getAnimals())

And you have

let getAnimals() : HttpHandler =
    fun _ ctx -> task { 
        let animalTypeFromQuery = ctx.GetQueryStringValue "type"
        let animalType =
            match animalTypeFromQuery with
            | Ok t    -> Some t
            | Error _ -> None
        ...
    }

I do not know if this is the official practice, I found this practice in some F# github repos.

like image 5
psfinaki Avatar answered Oct 19 '22 10:10

psfinaki