This is the way I do it - it seems to work, but I've only just started using Liberator, so there might be better or more correct ways of doing this!
I think what you need is a handle-created handler. For example -
(defresource shopping-calc
:allowed-methods [:post]
:available-media-types ["application/json"]
:malformed? (fn [context]
(let [params (get-in context [:request :params])]
(or (empty? params)
(is-malformed? params))))
:handle-malformed (fn [context]
(let [params (get-in context [:request :params])]
(generate-string (handle-malformed-calc params))))
:handle-created (fn [context]
(let [params (get-in context [:request :params])]
(generate-string (calculate-total params)))))
and I have a handler-created handler like this
(defn calculate-total [params]
{:total (calc params)})
I also use the ring/json middleware and in my dev environment, add the liberator trace facility. The Liberator trace facility is very handy as it will add headers to the response which show the decision points for Liberator. So, for you problem, it probably would have shown that Liberator was using the default handle-created handler, which just returns the headers. To return your own json, you need to define the handler.
Note that I'm not using the post! method. This is because in this example, I'm not actually creating some sort of new object/item, such as adding a record to some sort of store. If you were doing this, what you might do would be to use post! to add the record and have handle-created defined to then get the new record (possibly with other new fields, such as a record id or timestamp etc) and return it.
I use the :malformed? and handle-malformed to do basic error checking. If :malformed? returns true, the handle-malformed header is called, which returns an error status and an error message in the json body. I find it helps a lot to have your errors also returned in json so that you can handle everything consistently on the client end.
My handlers and middleware definitions are below. Note that as I'm serving up both application and api routes, they are a little more complicated because I want some middleware applied to some routes and other middleware applied to others. There is also a minor bug in ring/ring-defaults which, once fixed, will modify things as currently I cannot use the wrap-defaults site-api middleware. Note the wrap-trace middleware.
(def app
(if (env :dev)
(routes (-> api-routes
(wrap-reload)
(wrap-routes wrap-json-params)
(wrap-routes wrap-defaults api-defaults)
(wrap-routes wrap-trace :header :ui))
(-> app-routes
(wrap-routes wrap-error-page)
(wrap-routes wrap-exceptions)))
(routes (-> api-routes
(wrap-routes wrap-json-params)
(wrap-routes wrap-defaults api-defaults))
app-routes)))
:new? true
to your resource might help? (If you really want to return201 Created
, that is.) – Snowslidetrue
onnew?
. – Xerography