oliyh / martian

The HTTP abstraction library for Clojure/script, supporting OpenAPI, Swagger, Schema, re-frame and more
MIT License
525 stars 42 forks source link

No matching content-type available for `application-json` #184

Closed LucianoLaratelli closed 10 months ago

LucianoLaratelli commented 10 months ago

Hello,

I'm trying out Martian for the YNAB API:

(ns user
  (:require [martian.clj-http :as martian-http]
            [martian.core :as martian]))

(def add-authentication-header
  {:name ::add-authentication-header
   :enter (fn [ctx]
            (assoc-in ctx [:request :headers "Authorization"] "Authorization: Bearer my-cool-bearer-token"))})

(def m (martian-http/bootstrap-openapi
        "https://api.ynab.com/papi/open_api_spec.yaml"
        {:interceptors (concat martian/default-interceptors
                               [add-authentication-header])}))

But I'm getting this message:

user> (martian/response-for m :get-budgets)
No matching content-type available {:supported-content-types #{}, :available-content-types (application/json), :header Content-Type}
No matching content-type available {:supported-content-types #{}, :available-content-types (application/json), :header Content-Type}
No matching content-type available {:supported-content-types #{}, :available-content-types (application/json), :header Content-Type}
;; => nil

What am I doing wrong here? I tried setting content-type manually with an interceptor:

(def add-json-header
  {:name ::add-json-header
   :enter (fn [ctx]
            (assoc-in ctx [:request :headers "Content-Type"] "application/json"))})

But got the same result.

oliyh commented 10 months ago

Hello,

There are a couple of things to be aware of here:

  1. martian.core/default-interceptors does not contain the content encoding/decoding interceptors, or the perform-request interceptor you need for a functioning martian. You need to use martian.clj-http/default-interceptors in this instance.
  2. If your interceptor modifies the request, it needs to go before the perform-request interceptor (which is at the end of the default interceptors).

Hopefully then, this code will work:

(ns user
  (:require [martian.clj-http :as martian-http]
            [martian.core :as martian]))

(def add-authentication-header
  {:name ::add-authentication-header
   :enter (fn [ctx]
            (assoc-in ctx [:request :headers "Authorization"] "Authorization: Bearer my-cool-bearer-token"))})

(def m (martian-http/bootstrap-openapi
        "https://api.ynab.com/papi/open_api_spec.yaml"
        {:interceptors (concat [add-authentication-header]
                               martian-http/default-interceptors)}))
mmeroberts commented 10 months ago

I am also seeing the No matching content-type available {:supported-content-types #{}, :available-content-types (application/json), :header Content-Type} with the following call:

(def m (martian-http/bootstrap-openapi "resources/descriptors.yaml"
                                       {:interceptors
                                        (concat [add-authentication-header
                                                 allow-insecure] 
                                                martian/default-interceptors)}))

Is there some extra encoding that I need to add? If I do two calls to the explore function the first gives me the errors, the second does not.

oliyh commented 10 months ago

Hi @mmeroberts ,

As above, you need to change martian/default-interceptors to martian-http/default-interceptors as only the latter contains the encoding/decoding and perform-request interceptors that you need.

Cheers

mmeroberts commented 10 months ago

Hi @mmeroberts ,

As above, you need to change martian/default-interceptors to martian-http/default-interceptors as only the latter contains the encoding/decoding and perform-request interceptors that you need.

Cheers

My issue was fixed when I added a specific encoder for application/yaml

Thanks

oliyh commented 10 months ago

Hi @mmeroberts thanks for the update. Interesting idea about another function on the API to identify potential issues. Martian already has spec instrumentation to help when specifying your own API without swagger, perhaps that could also be leveraged to discover where there are no acceptable content types?

@LucianoLaratelli is your issue also resolved now (thanks for the update to the readme, I think it is clearer now)?

LucianoLaratelli commented 10 months ago

Yes, all good on my end. Thank you for the help!