Как получить параметр запроса в 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;