I’m trying to figure out how to get yada to select a content-type for a response based on a query param. The resource is set to produce #{"text/html" "application/json;q=0.9"}
, as html should be the default if there’s no Accept header and no relevant query param. However, the API user can send the param json=true
which should act as if they has sent an Accept header of application/json
. I know this is not good API design, but I have to support it for legacy reasons. In any case, I either produce an HTML string or a Clojure map based on (or json (.contains (yada/content-type ctx) "json"))
. I thought that yada would take a Clojure map and the fact that application/json is an allowed production type and produce an application/json
response, but it produces HTML. If I remove the quality ranking, I always get JSON, even for the strings. How can I set the content-type based purely on the data type I have to return when I don’t have an Accept header?
Should I manipulate the context by setting the request Accept header based on the query param?
The manual says that if I want complete control of the response, I can return a modified Response taken from the ctx, but that already has the negotiated media type set on it, which is text/html when there’s no accept header.
Yes, you can return the response and you can override that content type
You've figured it out
Thanks
But the response looks like this right before I get I change to modify it:
#yada.context.Response{:headers {}, :vary #{:media-type}, :produces {:media-type #yada.media_type.MediaTypeMap{:name text/html, :type text, :subtype html, :parameters {}, :quality 1.0}, :charset #yada.charset.CharsetMap{:alias UTF-8, :quality 1.0}}
After: #yada.context.Response{:headers {content-type application/json}, :vary #{:media-type}, :produces {:media-type #yada.media_type.MediaTypeMap{:name text/html, :type text, :subtype html, :parameters {}, :quality 1.0}, :charset #yada.charset.CharsetMap{:alias UTF-8, :quality 1.0}}, :body ...}
And I still get html, so I must be doing something wrong
What did you modify?
I set the header and body
If you are returning the response yourself you then have to do the conversion of the body to whatever you need.
But the produces seems to win
Yada won't automatically convert for you
Content negotiation happens before the response function
You can renegotiate manually but its off piste
Off piste?
I think ideally I'd prefer to renegotiate manually as that seems cleaner. Just don't know how
Sorry, an expression meaning you're straying outside of yada 's functionality but this tends to happen when you are forced to cope with bad practices
Exactly my case lol
There's code in the yada conneg ns
Okay I'll take a look
This works:
(if json
(-> response
(assoc-in [:produces :media-type] (yada.media-type/string->media-type "application/json"))
(assoc :body body))
body)
@malcolmsparks thanks for your help