Fork me on GitHub
#yada
<
2018-02-16
>
neverfox15:02:03

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?

neverfox15:02:51

Should I manipulate the context by setting the request Accept header based on the query param?

neverfox16:02:09

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.

malcolmsparks16:02:14

Yes, you can return the response and you can override that content type

malcolmsparks16:02:26

You've figured it out

neverfox16:02:59

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}}

neverfox16:02:46

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 ...}

neverfox16:02:19

And I still get html, so I must be doing something wrong

malcolmsparks16:02:35

What did you modify?

neverfox16:02:17

I set the header and body

malcolmsparks16:02:28

If you are returning the response yourself you then have to do the conversion of the body to whatever you need.

neverfox16:02:43

But the produces seems to win

malcolmsparks16:02:44

Yada won't automatically convert for you

malcolmsparks16:02:13

Content negotiation happens before the response function

malcolmsparks16:02:30

You can renegotiate manually but its off piste

neverfox16:02:48

Off piste?

neverfox16:02:31

I think ideally I'd prefer to renegotiate manually as that seems cleaner. Just don't know how

malcolmsparks16:02:56

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

neverfox16:02:12

Exactly my case lol

malcolmsparks16:02:38

There's code in the yada conneg ns

neverfox16:02:54

Okay I'll take a look

neverfox16:02:11

This works:

neverfox16:02:19

(if json
        (-> response
            (assoc-in [:produces :media-type] (yada.media-type/string->media-type "application/json"))
            (assoc :body body))
        body)

neverfox16:02:38

@malcolmsparks thanks for your help