Compojure API

What is it?

An attempt to unify things you need around a web api

  • Uses compojure's api syntax 
  • Integrates with prismatic/Schema for route validation
  • Adds swagger integration for api docs
  • Lots of "bonus" features such as bi-directional routing, resources, etc

 

Because of all this the dependency tree is LARGE

lein deps :tree

Let's jump into a demo and take a look

This will give us some context for the rest of our slides.

 

https://github.com/philipsdoctor/compojure-api-demo

 

Screen Shots (if issues)

Routes have descriptions and schemas.

Screen Shots (if issues)

App setup and UI descriptions

Screen Shots (if issues)

What is Compojure?

A routing library, one of the most popular downloaded libraries for all of Clojure

  • Compojure's routing is somewhat difficult to extend due to macros
  • Compojure-API creates a layer on top of compojure with a compatible route API so that routes created in compojure will run in compojure-api
  • Compojure-API adds meta-data

https://github.com/metosin/compojure-api/blob/master/src/compojure/api/core.clj

What is Prismatic/Schema?

A library for declarative data description and Validation

https://github.com/plumatic/schema

(def Data
  "A schema for a nested data type"
  {:a {:b s/Str
       :c s/Int}
   :d [{:e s/Keyword
        :f [s/Num]}]})

What problem is Schema solving?

  • We're not trying to reinvent WSDLs or other sadness
  • Common (what I think is) an anti-pattern
 (POST "/foo/:bar" {:keys [body params]}
   (foobar/foo (merge params (walk/keywordize-keys body)))
   {:status 200})

--

or **kwargs if you're a python guy
  • Understanding what is being passed becomes a multi-project grep game.

What is Swagger?

  • Extremely popular library for API design, takes into account both UI documentation and code generation
  • http://swagger.io/
  • Not specifically Clj, but it's nice to use someone's popular battle tested library sometimes
  • TONS of tooling, docs, examples, projects, etc
  • Apache2 license

How do these fit together?

  • Start with a route
  • Add schema information to it
  • Schema information will be applied to the route to validate it
  • Schema information will drive the generation of the swagger UI

Code!

Migration!

  • You can do this a route at a time, no major rewrites!
  • Simply don't add schema to a route, it won't get validated and you can use :middleware key to use old middleware in case compojure API's middleware doesn't work with the old route (extremely likely)

Gotchas!

  • Compojure-API has A LOT of middleware, and it may be applied both before your custom middleware on inbound requests and then after your customer middleware on outbound replies
  • Carefully test error cases including things like incorrect/missing content type headers, these error cases may not conform to your route schemas and create a validation error that hides the issue (or result in no reply at all). 

Testing!

    (let [app (build-app)
          req (api-request :post "/v1/bar?req-id=tako" {:totalTxBytes 10
                                                        :planId "4123EF"
                                                        :rxPercentage 98.02})
          resp (app req)]
      (is (= 200 (:status resp))))

Resources

  • https://github.com/metosin/compojure-api
  • http://swagger.io/
  • https://github.com/plumatic/schema
  • https://github.com/philipsdoctor/compojure-api-demo

Compojure API

By Philip Doctor

Compojure API

  • 1,579