Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set a Json response in suave webpart

Tags:

json

http

php

f#

suave

i'm begining with Suave and F#. I'm trying to pass a json serialized object in my webpart to get it in my response.

In php i have this

<?php
header('Access-Control-Allow-Credentials:true');
header('Access-Control-Allow-Headers:Content-Type, Accept');
header('Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Origin:*');
?>
{
 "player1Key":"hdegftzj25",
 "gameKey":"aegfhzkfszl74852"
}

and with this i get my json object, then i tried to do the same with Suave and Newtonsoft.Json

type gameCreate= {
    player1Key : string
    gameKey: string
}

let create= { player1Key = "BadBoys2"; gameKey = "zLUGgtrht4456" }

let json = Newtonsoft.Json.JsonConvert.SerializeObject(create)

//OK (acc |> Json.serialize |> Json.format )
let php =
request (fun r ->
    match r.queryParam "playerName" with
    | Choice1Of2 name ->  OK (movies |> Json.serialize(json) |> Json.format(json))
                        //|>  Response.response(Json.toJson(info))
                        //|>  OK
    | Choice2Of2 msg -> BAD_REQUEST msg)

let webPart = 
choose [
path "/" >=> (OK "Home")
path "/elm/api/create.php" >=> php
]

startWebServer defaultConfig webPart

So i can create and serialize a json object but i don't know how to pass it as http response in my web part and with the above code i keep on getting error on my expressions type in my let php

like image 971
user3525616 Avatar asked Mar 10 '23 23:03

user3525616


2 Answers

Looks like you've pulled in a few Json serialization libraries too many - you seem to mix bits of Json.NET and Chiron (which is used in the tutorial), to no great effect...

Let's take a step back. Suave comes with its own Json serialization module, so you can get something working just by using that. Here's how it would look:

let php =
    request (fun r ->
        match r.queryParam "playerName" with
        | Choice1Of2 name ->  
            let json : string = 
                create
                // this comes from Suave.Json, gives you a byte array
                |> Json.toJson           
                // converts the byte array into a string
                |> System.Text.Encoding.UTF8.GetString
            OK json
        | Choice2Of2 msg -> BAD_REQUEST msg)

Now, if you want, you can replace the Json.toJson call with either the Newtonsoft Json.NET or Chiron implementation (but hopefully not a mix of the two). As long as the types align, you should be fine.

For Chiron in particular, you're missing the ToJson static member on the type you want to serialize (this is something that your tutorial does mention). Json.NET has a generic serialize function that produces json corresponding to the record schema, so it's a bit easier to use out of the box, but also requires more work to customize the output if needed.

like image 88
scrwtp Avatar answered Mar 16 '23 18:03

scrwtp


If you want to return a HTTP 200 response with JSON and set HTTP headers in Suave, then you can use the Writers.setHeader function:

Writers.setHeader "Access-Control-Allow-Credentials" "true" >=>
Writers.setHeader "Access-Control-Allow-Headers:Content-Type" "Accept" >=>
Writers.setHeader "Access-Control-Allow-Methods" "GET, POST, PUT, DELETE, OPTIONS" >=>
Writers.setHeader "Access-Control-Allow-Origin" "" >=>
Successful.OK (movies |> Json.serialize |> Json.format)

The whole thing is an expression that constructs a WebPart which you can then compose with other web parts using the functions provided by Suave. So if you wanted to pattern match before setting the headers, you'd use something like:

let php = request (fun r ->
  match r.queryParam "playerName" with
  | Choice1Of2 name ->  
      Writers.setHeader "Access-Control-Allow-Credentials" "true" >=>
      Writers.setHeader "Access-Control-Allow-Headers:Content-Type" "Accept" >=>
      Writers.setHeader 
        "Access-Control-Allow-Methods" "GET, POST, PUT, DELETE, OPTIONS" >=>
      Writers.setHeader "Access-Control-Allow-Origin" "" >=>
      Successful.OK (movies |> Json.serialize |> Json.format)
  | Choice2Of2 msg -> BAD_REQUEST msg)

As you are setting the CORS headers, this snippet might also help.

like image 23
Tomas Petricek Avatar answered Mar 16 '23 18:03

Tomas Petricek