Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

response-for returns nil #154

Open
rkirchofer opened this issue Jun 16, 2022 · 3 comments
Open

response-for returns nil #154

rkirchofer opened this issue Jun 16, 2022 · 3 comments

Comments

@rkirchofer
Copy link
Contributor

I'm struggling to get response-for to work when I have an interceptor that adds some headers.

(defn my-service
  [{:keys [base-url api-key http-timeout]
    :or {http-timeout 30000}}]
  (martian-http/bootstrap
   base-url
   [{:route-name :get-item
     :produces ["application/json"]
     :consumes ["application/json"]
     :path-parts ["/api/" :id]
     :path-schema {:id sch/Str}
     :method :get}]
   {:interceptors (concat martian/default-interceptors
                          [{:name ::add-api-key
                            :enter (fn [ctx]
                                     (update-in ctx [:request :headers]
                                                assoc :x-api-key api-key))}
                           {:name ::add-timeouts
                            :enter (fn [ctx]
                                     (update-in ctx
                                                [:request :headers]
                                                assoc
                                                :socket-timeout http-timeout
                                                :conn-timeout http-timeout))}])}))

(let [base-url "https://www.my-service.com"
      api-key "mochi"]
  (fake/with-fake-routes-in-isolation
    {"https://www.my-service.com/api/123"
     {:get (fn [req]
             {:status 200
              :body (cheshire.core/generate-string {:a "b"})})}}
    (martian/response-for (my-service {:base-url base-url
                                       :api-key api-key})
                          :get-item
                          {:id "123"})
    (comment nil)
    (martian/request-for (my-service {:base-url base-url
                                      :api-key api-key})
                         :get-item
                         {:id "123"})
    (comment {:method :get
              :url "https://www.my-service.com/api/123"
              :headers {:x-api-key "mochi"
                        :socket-timeout 30000
                        :conn-timeout 30000}})
    (http/request (martian/request-for (my-service {:base-url base-url
                                                    :api-key api-key})
                                       :get-item
                                       {:id "123"}))
    (comment {:status 200
              :body "{\"a\":\"b\"}"
              :request-time 1
              :orig-content-encoding nil})))
(defn my-service
  [{:keys [base-url api-key http-timeout]
    :or {http-timeout 30000}}]
  (martian-http/bootstrap
   base-url
   [{:route-name :get-item
     :produces ["application/json"]
     :consumes ["application/json"]
     :path-parts ["/api/" :id]
     :path-schema {:id sch/Str}
     :method :get}]))

(let [base-url "https://www.my-service.com"
      api-key "mochi"]
  (fake/with-fake-routes-in-isolation
    {"https://www.my-service.com/api/123"
     {:get (fn [req]
             {:status 200
              :body (cheshire.core/generate-string {:a "b"})})}}
    (martian/response-for (my-service {:base-url base-url
                                       :api-key api-key})
                          :get-item
                          {:id "123"})
    (comment {:status 200
              :body "{\"a\":\"b\"}"
              :request-time 0
              :orig-content-encoding nil})))

I also tried adding :headers-schema {:x-api-key sch/Str} but it just says Could not coerce value to schema: {:x-api-key missing-required-key} and :headers-schema {(sch/optional-key :x-api-key) sch/Str} doesn't change anything.

@oliyh
Copy link
Owner

oliyh commented Jun 17, 2022

Hi,

I think the problem comes from here:

:interceptors (concat martian/default-interceptors ...

The default interceptors in martian.core do not include the "implementation" interceptors that actually make the http request. These you will find in martian.clj-http/default-interceptors, or any of the other implementation namespaces (not sure which you are using).

Note that your interceptors will run after the martian interceptors, which include setting and validating the headers schema, so if you set the header schema but only populate the extra data after that interceptor as run then you will get the error above.

Hope this helps

@rkirchofer
Copy link
Contributor Author

Thanks, that's a huge help!

I'm using martian.clj-http now and I reordered the interceptors. I thought that you were suggesting that I needed to reorder them so that it it will assoc the api key before the martian default interceptors run but it's still failing schema validation.

(defn my-service
  [{:keys [base-url api-key http-timeout]
    :or {http-timeout 30000}}]
  (martian-http/bootstrap
   base-url
   [{:route-name :get-item
     :produces ["application/json"]
     :consumes ["application/json"]
     :headers-schema {:x-api-key sch/Str}
     :path-parts ["/api/" :id]
     :path-schema {:id sch/Str}
     :method :get}]
   {:interceptors (concat [{:name ::add-api-key
                            :enter (fn [ctx]
                                     (update-in ctx [:request :headers]
                                                assoc :x-api-key api-key))}]
                          martian-http/default-interceptors)}))

(let [base-url "https://www.my-service.com"
      api-key "mochi"]
  (fake/with-fake-routes-in-isolation
    {"https://www.my-service.com/api/123"
     {:get (fn [req]
             {:status 200
              :body (cheshire.core/generate-string {:a "b"})})}}
    (martian/response-for (my-service {:base-url base-url
                                       :api-key api-key})
                          :get-item
                          {:id "123"})))



   ;; Could not coerce value to schema: {:x-api-key missing-required-key}
   ;; {:type :schema-tools.coerce/error,
   ;;  :schema {:x-api-key java.lang.String},
   ;;  :value {:id "123"},
   ;;  :error {:x-api-key missing-required-key}}

I only added :headers-schema because I thought that's why it wasn't working. I could just remove it but I'm interested to learn what I'm doing wrong.

Thanks so much for the help!

@oliyh
Copy link
Owner

oliyh commented Jun 21, 2022

Hi,

Yes I was suggesting you reorder them as you have done, I expected that to work. It's possible Martian's headers interceptor is not merging properly. It's interesting that the value it sees is the map with your id. This means of course that you could pass the API key in the arguments map to martian, but you probably don't want to arrange your prod code that way.

I'll try to find time to look into this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants