yada

neverfox 2018-02-16T15:53:03.000157Z

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?

neverfox 2018-02-16T15:54:51.000455Z

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

neverfox 2018-02-16T16:11:09.000031Z

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.

malcolmsparks 2018-02-16T16:12:14.000089Z

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

malcolmsparks 2018-02-16T16:12:26.000780Z

You've figured it out

neverfox 2018-02-16T16:12:30.000734Z

Thanks

neverfox 2018-02-16T16:12:59.000320Z

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

neverfox 2018-02-16T16:14:46.000637Z

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

neverfox 2018-02-16T16:15:19.000650Z

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

malcolmsparks 2018-02-16T16:18:35.000110Z

What did you modify?

neverfox 2018-02-16T16:19:17.000705Z

I set the header and body

malcolmsparks 2018-02-16T16:19:28.000092Z

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

neverfox 2018-02-16T16:19:43.000527Z

But the produces seems to win

malcolmsparks 2018-02-16T16:19:44.000066Z

Yada won't automatically convert for you

malcolmsparks 2018-02-16T16:20:13.000295Z

Content negotiation happens before the response function

malcolmsparks 2018-02-16T16:20:30.000633Z

You can renegotiate manually but its off piste

neverfox 2018-02-16T16:20:48.000183Z

Off piste?

neverfox 2018-02-16T16:21:31.000696Z

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

malcolmsparks 2018-02-16T16:21:56.000208Z

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

neverfox 2018-02-16T16:22:12.000530Z

Exactly my case lol

malcolmsparks 2018-02-16T16:22:38.000608Z

There's code in the yada conneg ns

neverfox 2018-02-16T16:22:54.000033Z

Okay I'll take a look

neverfox 2018-02-16T16:29:11.000649Z

This works:

neverfox 2018-02-16T16:29:19.000268Z

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

neverfox 2018-02-16T16:54:38.000449Z

@malcolmsparks thanks for your help