Fork me on GitHub
#biff
<
2023-11-04
>
Lyn Headley03:11:09

Any examples using biff to serve a simple route to which you can POST a json body? I imagine I can just (get ctx :body) and call cheshire/decode on that?

Jacob O'Bryant03:11:41

the example app comes with a /api/echo endpoint that you can post stuff to: https://github.com/jacobobryant/biff/blob/5295ec19947eae0a1c71a8d9365c32ed081e3344/example/src/com/example/app.clj#L140 if you set Content-Type: application/json on your request, it'll get parsed automatically

Jacob O'Bryant03:11:15

or at least it should--it's not a feature I use often 🙂

gratitude-thank-you 1
Lyn Headley11:11:59

I will investigate further since I'm still confused about 1) This example is setting the content type on a response, not a request, which would not seem to effect how the incoming posted body is parsed. 2) The key of the function is params, which I'm not sure how that would be related to a parsed json post body. Maybe it is the parsed json post body.

Lyn Headley12:11:28

Ok, your example works. You meant to set the content-type on the request in the headers created by the client. params is indeed the parsed json post body. Interestingly, this doesn't quite work if you json post an array. See below Thank you.

(defn stripe-web-hook-handler [{:keys [params]}]
  {:status 200
   :headers {"content-type" "application/json"}
   :body params})

(comment
  (client/post ""
               {:content-type :json
                :form-params []}))

Lyn Headley12:11:42

{:cached nil,
 :request-time 61,
 :repeatable? false,
 :protocol-version {:name "HTTP", :major 1, :minor 1},
 :streaming? true,
 :http-client
 #object[org.apache.http.impl.client.InternalHttpClient 0x6fb6c70c "org.apache.http.impl.client.InternalHttpClient@6fb6c70c"],
 :chunked? false,
 :reason-phrase "OK",
 :headers
 {"Connection" "close",
  "Content-Type" "application/json;charset=utf-8",
  "Content-Length" "2",
  "Server" "Jetty(10.0.7)"},
 :orig-content-encoding nil,
 :status 200,
 :length 2,
 :body "{}",
 :trace-redirects []}

Lyn Headley12:11:07

I would expect :body above to be "[]"

Lyn Headley12:11:43

Luckily, I don't need to accept arrays now, but in other contexts I have wanted to.

m.q.warnock14:11:16

interesting that a bare array doesn't work, and that I've never run into it (I have lots of endpoints expecting json); I guess I always use an object at the top level, because if I'm sending a list, I want it labeled. I suppose it can't work, because the muuntaja middleware will also parse get and posted form params into that same object. btw, you can send application/edn, and it will also be parsed into params. It's much nicer when your client is also clojure[script/dart]; you can return it too, though the client-side encoding/parsing will likely be up to you. I just have one post-edn function in my clojuredart client that prn-str's the post-body, expects edn in return, deals with cookies, etc, so my whole api on both sides is free of the kind of type-mangling you have to do with json.

Jacob O'Bryant17:11:39

hmmm yeah, if possible I would probably just set a top-level key with the array. makes it easier to add more stuff to the request/response later on if you neei to anyway, E.g. pagination info. (I wonder what that example looks like if you POST a non-empty array by the way?) if you do ever need different behavior, you can mess around with the middleware stack. new projects have it all in a middleware.clj file, though that's a relatively recent addition (couple months ago I think).

Lyn Headley18:11:32

posting a non-empty array also results in an empty map as above

👍 1