Hi everyone,
I'm very excited to introduce *Martian*, a Clojure/script HTTP client wrapper which simplifies HTTP calls without surrendering control to an opaque library. Find it on Github and Clojars now: https://github.com/oliyh/martian It uses Swagger descriptions to name operations, map parameters to form the request map and serialise it as efficiently as possible, and is built using pedestal's interceptor concept making it composable and extensible. You can use your favourite HTTP client, with implementations provided for httpkit, clj-http and cljs-http and extend behaviour any way you wish by providing your own interceptors to the chain. The following example shows how simple it can be to make HTTP calls to a Swagger API: (require '[martian.core :as martian] '[martian.clj-http :as martian-http]) (let [m (martian-http/bootstrap-swagger "https://pedestal-api.herokuapp.com/swagger.json")] (martian/response-for m :create-pet {:name "Doggy McDogFace" :type "Dog" :age 3}) ;; => {:status 201 :body {:id 123}} (martian/response-for m :get-pet {:id 123})) ;; => {:status 200 :body {:name "Doggy McDogFace" :type "Dog" :age 3}} Martian offers a pure client with no server code or dependency, no compile time dependencies on the API, is cross platform, allows you full access to the request and response data and your own choice of HTTP library. Using Swagger descriptions allows Martian to apply runtime schema checks to the parameters you send in requests and even provide dummy implementations that return generated responses instead of calling a real server. This opens up areas of code that would previously be difficult to test and makes them fully transparent. As well as performing requests and returning the response, Martian lets you explore APIs, build URLs and request maps without executing them. (require '[martian.core :as martian] '[martian.clj-http :as martian-http]) ;; bootstrap the martian instance by simply providing the url serving the swagger description (let [m (martian-http/bootstrap-swagger "https://pedestal-api.herokuapp.com/swagger.json")] ;; explore the endpoints (martian/explore m) ;; => [[:get-pet "Loads a pet by id"] ;; [:create-pet "Creates a pet"]] ;; explore the :get-pet endpoint (martian/explore m :get-pet) ;; => {:summary "Loads a pet by id" ;; :parameters {:id s/Int}} ;; build the url for a request (martian/url-for m :get-pet {:id 123}) ;; => https://pedestal-api.herokuapp.com/pets/123 ;; build the request map for a request (martian/request-for m :get-pet {:id 123}) ;; => {:method :get ;; :url "https://pedestal-api.herokuapp.com/pets/123" ;; :headers {"Accept" "application/transit+msgpack" ;; :as :byte-array} If you need to add your own behaviour it's easy - the interceptor pattern lets you add your own interceptors to decorate requests before they are sent and process the responses when they come back, as shown in this example: (require '[martian.core :as martian] '[martian.clj-http :as martian-http]) (def add-authentication-header {:name ::add-authentication-header :enter (fn [ctx] (assoc-in ctx [:request :headers "Authorization"] "Token: 12456abc"))}) (def request-timer {:name ::request-timer :enter (fn [ctx] (assoc ctx ::start-time (System/currentTimeMillis))) :leave (fn [ctx] (->> ctx ::start-time (- (System/currentTimeMillis)) (format "Request to %s took %sms" (get-in ctx [:handler :route-name])) (println)) ctx)}) (let [m (martian-http/bootstrap-swagger "https://pedestal-api.herokuapp.com/swagger.json" {:interceptors (concat martian/default-interceptors [add-authentication-header martian-http/encode-body (martian-http/coerce-response) request-timer martian-http/perform-request])})] (martian/response-for m :all-pets {:id 123})) ;; Request to :all-pets took 38ms ;; => {:status 200 :body {:pets []}} Martian can even be used for endpoints that don't have Swagger definitions if you describe them yourself in the Swagger format. There'll be more on this in future updates. There are more examples and use cases on the Github README https://github.com/oliyh/martian The project is new so any feedback is very welcome, including pull requests and issues on Github. I hope you find it useful! Oliy -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.