Как получить параметр запроса в F# Saturn Framework?

Скажем, у нас есть этот веб-сервер для обработки запросов:

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

Этот синтаксис описан в документации и продемонстрирован в примере.

Теперь, что, если я хочу иметь параметр в URL-запросе, например, для фильтрации результатов?

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

Это ничего не делает:

getf "/api/zoo/animals?type=%s" getAnimalsByType

3 ответа

Решение

Один из способов - использовать функцию GetQueryStringValue контекста. Возвращает Result, struct DU.

Таким образом, вы остаетесь с первоначальной подписью (просто удалите косую черту):

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

И у тебя есть

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

Я не знаю, является ли это официальной практикой, я нашел эту практику в некоторых репозиториях F# github.

Смотрите пример здесь:

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

Он показывает, как связать данные из строки запроса, чтобы вам не приходилось использовать GetQueryStringValue

В вашем случае, я думаю, что-то подобное может сработать.

[<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
    }

боролся с параметрами POST в Gigraff POST

      #light "off"
open System.Text.RegularExpressions
open System.IO
open System.Text
open Microsoft.AspNetCore.Http
open Giraffe
open FSharp.Data.Sql
open Giraffe.ViewEngine

let indexView = createPage ("test post") [
...
   let row i d = tr [] [
        td [] [ str (string(i)) ];
        td [] [ str d ]] in
   let db_ctx = mssql.GetDataContext() in
   let rows = [ for r in db_ctx.Dbo.Data do 
           (row r.Id r.Data) done ] in
...  
   form [_method "POST"; _action "/"; _enctype "multipart/form-data"] [
       button [] [str "Add row!" ]  
       input [ _type "text"; _name "Id"]  
       input [ _type "text"; _name "Data"]
   ...
       div[] rows

]

а также

        let chk s = not (String.IsNullOrEmpty s)
  let indexHandler : HttpHandler =
    fun (next : HttpFunc) (ctx : HttpContext) -> task { return! (
         if ctx.Request.ContentType.StartsWith( "multipart/form-data") then begin 
           let id = (ctx.Request.Form.Item("Id").ToString()) in
           let data = (ctx.Request.Form.Item("Data").ToString()) in
           if chk id && chk data 
              && not (Regex.IsMatch( id,"[^\\d]"))  then begin
              let db_ctx = mssql.GetDataContext() in
              db_ctx.Dbo.Data.Create( int(id),data) |> ignore;
              db_ctx.SubmitUpdates();
           end;
         end;
         htmlView indexView
      ) next ctx
   }

а также

      GET >=> route "/" >=> indexHandler;
POST >=> route "/" >=> indexHandler;
Другие вопросы по тегам