Options for building REST APIs in Clojure
Liberator
Compojure
API Groups
User / Dataset / Service provider management
Possibly defined in Avro
{ "name" : "actorInfo", "fields" : [{"name" : "actorid", "type" : "string"}, {"name" : "name", "type" : "string"}, {"name" : "age", "type" : "int"}, {"name" : "phone", "type" : "string"}] }
{ "name" : "actorInfoResponse", "fields" : [{"name" : "actorid", "type" : "string"}, {"name" : "privateKey", "type" : "string"}, {"name" : "state", "type" : "string"}, {"name" : "creationTime", "type" : "long"}] }
Specify a ring handler
(def app (api ;;configuration (context "/some/path" ;;API Groups or Resources (GET "/someresource" ;;GET/POST/PUT methods ;; ))))
{:coercion :schema :swagger {:ui "/" :spec "/swagger.json" :data {:info {:title "Aquarium API" :description "API methods for Aquarium"} :tags [{:name "api", :description "Manage assets, actors "}] :consumes ["application/json"] :produces ["application/json"] }}}
(s/defschema RegisterActorReq {:actorId s/Str (s/optional-key :name) s/Str (s/optional-key :privateKey) s/Str} )
(s/defschema RegisterActorResp {:actorId s/Str (s/optional-key :state) s/Str (s/optional-key :privateKey) s/Str (s/optional-key :creationTime) s/Num } )
(GET "/:actorId" [] :return RegisterActorResp :path-params [actorId :- s/Str] :summary "Returns data on actor" (ok (get-actor actorId)))
(POST "/" [] :return RegisterActorResp :body [user RegisterActorReq] :summary "Register an actor" (let [res (register-actor user)] (created nil res)))
(GET "/" [] :return AssetListResp :query-params [from :- s/Str, to :- s/Str] (ok (some-function from to)
file download: tries to encode file as json disable response encoding
(GET "/:assetId" [] :return File :path-params [assetId :- s/Str] :summary "Downloads asset from provider" (let [{:keys [path content-type]} (get-asset-map assetId)] (-> (io/file path) (io/input-stream) (ok) (header "Content-type" content-type) (muuntaja/disable-response-encoding) )))
Using Ring mock
(let [user {:actorId "actorid123"} response (app (-> (mock/request :post "http://server/api/v1/actors/") (mock/content-type "application/json") (mock/body (cheshire/generate-string user)))) body (cheshire/parse-string (slurp (:body response)) true)] (is (= (:status response) 201)) (-> (s/check AssetResp body) nil? is) )
[ring.util.http-response :refer [ok header created not-found]]
[ring.middleware.multipart-params :refer [wrap-multipart-params]] [ring.swagger.upload :as upload]
[muuntaja.core :as muuntaja]
Tweet at @kaaldaari