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

How to #137

Closed rgkirch closed 2 years ago

rgkirch commented 2 years ago

The vcr docs inject the record interceptor after perform-request but my code only records if I inject before perform-request.

vcr docs:

(inject http/default-interceptors
        (vcr/record opts)
        :after (:name http/perform-request))

my code:

(def vcr-opts
  {:store {:kind :atom
           :store (atom {})}
   :extra-requests :repeat-last})
(def m (martian-http/bootstrap "http://worldtimeapi.org/api/ip"
                               [{:route-name :time
                                 :path-parts []
                                 :method :get}]
                               {:interceptors (-> martian-http/default-interceptors
                                                  (inject (vcr/record vcr-opts)
                                                          :before (:name martian-http/perform-request))
                                                  (inject (vcr/playback vcr-opts)
                                                          :after (:name martian-http/perform-request))
                                                  (conj {:name ::cors
                                                         :enter #(assoc-in % [:request :with-credentials?] false)}))}))

(go (println (:unixtime (:body (<! (martian/response-for m :time))))))
(pprint (deref (get-in vcr-opts [:store :store])))

I'm not able to get playback to work either before or after perform-request. Re-running response-for just accumulates responses but sends a new request each time. I want to only make a request the first time and the re-use the cached response.

I've tried injecting playback both before and after perform-request but didn't notice any difference.

For completness, here's what's accumulating in the store atom.

{:time
 {{}
  {0
   {:status 200,
    :success true,
    :body
    {:unixtime 1643559924,
     :headers
    {"cache-control" "max-age=0, private, must-revalidate",
     "content-type" "application/json; charset=utf-8"},
    :trace-redirects
    ["http://worldtimeapi.org/api/ip"
     "http://worldtimeapi.org/api/ip"],
    :error-code :no-error,
    :error-text ""},
   1
   {:status 200,
    :success true,
    :body
    {:unixtime 1643559924,
     :headers
    {"cache-control" "max-age=0, private, must-revalidate",
     "content-type" "application/json; charset=utf-8"},
    :trace-redirects
    ["http://worldtimeapi.org/api/ip"
     "http://worldtimeapi.org/api/ip"],
    :error-code :no-error, 
    :error-text ""}}}}

Thanks!

rgkirch commented 2 years ago

Oh, if I keep the same store atom but use a new bootstrap then maybe it would use the cached values. I'm probably having trouble because I'm not using it as intended.

rgkirch commented 2 years ago

record injected after perform-request gives me a store with nils like {0 nil, 1 nil, 2 nil}

Strange since I have to inject after in order to see the response...

(inject {:name ::spy
         :leave #(doto % pprint)}
        :after (:name martian-http/perform-request))
oliyh commented 2 years ago

Hello,

Have you referred to the test? https://github.com/oliyh/martian/blob/04738957ecceca7b8900eacb70f223bf3a18f8e9/vcr/test/martian/vcr_test.cljc#L49

For recording, it needs to be before the http interceptor. For playback, it replaces the http interceptor.

Very possible that that readme is not correct, apologies for that if it's wasted some time for you.

Hope this helps

oliyh commented 2 years ago

Hello,

I've improved the readme and ensured the code examples are correct, hope this helps.

rgkirch commented 2 years ago

Thank you for updating the docs! All of your feedback has been extremely helpful and I'm enjoying using martian. I'm sorry for not responding to your last message; I got hung up with something else.

I noticed that the vcr tests don't use :replace. Is there an issue with the tests or can the playback interceptor implicitly replace the perform-request interceptor?

Thanks again!

oliyh commented 2 years ago

Hello,

In the test there is a subtle difference of using martian.core/interceptors vs the readme which uses martian.clj-http/interceptors, the latter containing the perform-request interceptor while the former does not. The playback needs to replace this one to prevent the actual request being made, but in the test it isn't there to begin with.

Thanks for your contributions and feedback, they've been very helpful.

Cheers

rgkirch commented 2 years ago

Congrats on the release. Cheers!