See also: compojure-api 1.1.x changelog
- bump spec-tools to 0.10.6
- notable changes: swagger
:namedefaults to"body"instead of""(diff)
- notable changes: swagger
- Add compatibility for 1.x coercions
- implies Schema backend
- fn from request->field->schema->coercer
- mostly often just
(constantly nil)or (constantly {:body matcher})
- BREAKING: removed
api-defaultsvars- add
-v2suffix to vars
- add
- exclude frankiesardo/linked #476
- Throw an error on malformed
:{body,query,headers}, in particular if anything other than 2 elements was provided- Disable check with
-Dcompojure.api.meta.allow-bad-{body,query,headers}=true
- Disable check with
- 50% reduction in the number of times
:{return,body,query,responses,headers,coercion,{body,form,header,query,path}-params}schemas/arguments are evaluated/expanded- saves 1 evaluation per schema for static contexts
- saves 1 evaluation per schema, per request, for dynamic contexts
- Fix: Merge
:{form,multipart}-params:info :public :parameters :formDatafield at runtime - Add
:outer-letsfield torestructure-paramresult which wraps entire resulting form - Remove
static-contextmacro and replace with equivalent expansion without relying on compojure internals. - Upgrade to ring-swagger 1.0.0 to fix memory leaks
- Fix empty spec response coercion. #413
- Add back
defapi(and deprecate it) - Remove potemkin #445
- Add back
compojure.api.routes/create - Add back
middleware(and deprecate it) - Make
context:dynamic by default - Add
:static trueoption tocontext - Add static context optimization coach
-Dcompojure.api.meta.static-context-coach=printto print hints-Dcompojure.api.meta.static-context-coach=assertto assert hints
- port unit tests from midje to clojure.test
- Update dependencies.
- Correct names for
:json&:stringcoercion type transformers - Update dependencies:
[metosin/spec-tools "0.9.1"] is available but we use "0.9.0"
[metosin/muuntaja "0.6.4"] is available but we use "0.6.3"
[metosin/ring-swagger "0.26.2"] is available but we use "0.26.1"-
Spec Coercion enchancements
- See spec-tools 0.9.0 changelog
- Coercion flows values through both
st/coerceandst/conform, by Miguel Ping
-
Updated dependencies:
[prismatic/schema "1.1.10"] is available but we use "1.1.9"
[metosin/muuntaja "0.6.3"] is available but we use "0.6.1"
[com.fasterxml.jackson.datatype/jackson-datatype-joda "2.9.8"] is available but we use "2.9.7"
[metosin/spec-tools "0.9.0"] is available but we use "0.8.2"- Expose full
clojure.specproblems for exception handlers, to use pretty-printers like expound:
(require '[compojure.api.sweet :refer :all])
(require '[ring.util.http-response :refer :all])
(require '[compojure.api.exception :as ex])
(require '[expound.alpha :as expound])
(def printer
(expound/custom-printer
{:theme :figwheel-theme, :print-specs? false}))
(def app
(api
{:coercion :spec
:exceptions
{:handlers
{::ex/request-validation
(fn [e data request]
(printer (:problems data))
(ex/request-validation-handler e data request))
::ex/response-validation
(fn [e data request]
(printer (:problems data))
(ex/response-validation-handler e data request))}}}
(GET "/math" []
:query-params [x :- int?, y :- int?]
:return {:total pos-int?}
(ok {:total (+ x y)}))))- updated deps:
[ring/ring-core "1.7.1"] is available but we use "1.7.0"
[metosin/spec-tools "0.8.2"] is available but we use "0.8.0"
[metosin/ring-http-response "0.9.1"] is available but we use "0.9.0"-
BREAKING: dropped support for Clojure 1.8.0
-
Latest features from spec-tools
- Swagger enchancements
- Better spec coercion via st/coerce using spec walking & inference: many simple specs (core predicates,
spec-tools.core/spec,s/and,s/or,s/coll-of,s/keys,s/map-of,s/nillableands/every) can be transformed without needing spec to be wrapped. Fallbacks to old conformed based approach.
-
new deps:
[metosin/spec-tools "0.8.0"]- update deps:
[com.fasterxml.jackson.datatype/jackson-datatype-joda "2.9.7"] is available but we use "2.9.6"
[ring/ring-core "1.7.0"] is available but we use "1.6.3"
[metosin/jsonista "0.2.2"] is available but we use "0.2.1"- update deps:
[metosin/muuntaja "0.6.0"] is available but we use "0.6.0-alpha4"- update deps:
[metosin/muuntaja "0.6.0-alpha4"] is available but we use "0.6.0-alpha3"-
BREAKING: Don't encode response
:bodyifContent-Typeheader is set. -
update deps:
[metosin/muuntaja "0.6.0-alpha3"] is available but we use "0.6.0-alpha1"- BREAKING: Use Muuntaja 0.6.0-alpha1
- See all changes in the Muuntaja CHANGELOG
- Highlights:
- Change default JSON Serializer from Cheshire to Jsonista
- Both Joda Time and java.time are supported out-of-the-box
- up to 6x faster encoding
- different configuration params, guarded by migration assertion
- BREAKING: by default Jackson tries to encode everything,
- e.g.
java.security.SecureRandomcan be serialized, via reflection
- e.g.
- BREAKING: decoding doesn't try to keep the field order for small maps
muuntaja.core/installhelper to add new formats:
(require '[compojure.api.sweet :refer :all])
(require '[ring.util.http-response :refer :all])
(require '[muuntaja.core :as m])
(require '[muuntaja.format.msgpack]) ;; [metosin/muuntaja-msgpack]
(require '[muuntaja.format.yaml]) ;; [metosin/muuntaja-yaml]
(def formats
(m/create
(-> m/default-options
(m/install muuntaja.format.msgpack/format)
(m/install muuntaja.format.yaml/format)
;; return byte[] for NIO servers
(assoc :return :bytes))))
(api
{:formats formats}
(POST "/ping" []
(ok {:ping "pong"})))- add
compojure.api.middleware/wrap-formatto support multiple apis (or api + external static routes)in a project, fixes #374
(require '[compojure.api.sweet :refer :all])
(require '[ring.util.http-response :refer [ok]])
(require '[compojurea.api.middeware :as middleware])
(-> (routes
(api
(POST "/echo1" []
:body [body s/Any]
(ok body)))
(api
(POST "/echo2" []
:body [body s/Any]
(ok body))))
(middleware/wrap-format))- update deps:
[ikitommi/linked "1.3.1-alpha1"] ;; waiting for original to update
[metosin/ring-swagger "0.26.1"] is available but we use "0.26.0"
[metosin/muuntaja "0.6.0-alpha1"] is available but we use "0.5.0"
[com.fasterxml.jackson.datatype/jackson-datatype-joda "2.9.6"] is available but we use 2.9.5"-
welcome spec transformers!! might break custom
coercionimplementations -
update deps:
[potemkin "0.4.5"] is available but we use "0.4.4"
[prismatic/schema "1.1.9"] is available but we use "1.1.7"
[frankiesardo/linked "1.3.0"] is available but we use "1.2.9"
[compojure "1.6.1"] is available but we use "1.6.0"
[metosin/spec-tools "0.7.0"] is available but we use "0.6.1"
[metosin/jsonista "0.2.0"] is available but we use "0.1.1"- Deal with coercion exceptions in async handlers, fixes #371, by Benjamin Teuber
- updated deps:
[metosin/ring-swagger "0.26.0"] is available but we use "0.25.0"
[metosin/spec-tools "0.6.1"] is available but we use "0.5.1"Maintenance 1.1 release, adding several patches from 2.0 branch.
- Backport: Fix context child resolution with compojure-bindings #370
- Backport: merge-vector #311
- Backport: Fix metadata position on defmacro to activate CIDER indent style #261
- updated deps:
[metosin/muuntaja "0.5.0"] is available but we use "0.4.1"- BREAKING: drop
defapi.def+apishould be used instead. - Cleanup conflicting transitive dependencies
- Supports both old (2.) and new (3.) swagger-uis.
[metosin/muuntaja "0.4.2"] is available but we use "0.4.1"
[metosin/ring-swagger "0.25.0"] is available but we use "0.24.3"- Rolled back the latest swagger-ui, which fails in
config not found. There is an issue in ring-swagger.
[metosin/ring-swagger-ui "2.2.10"] is available but we use "3.0.17"- updated deps:
[metosin/muuntaja "0.4.1"] is available but we use "0.4.0"-
Fixes Muuntaja-bug of randomly failing on
:bodyparameters with some server setups. -
updated deps:
[prismatic/plumbing "0.5.5"] is available but we use "0.5.4"
[metosin/muuntaja "0.4.0"] is available but we use "0.3.3"
[ring/ring-core "1.6.3"] is available but we use "1.6.2"
[metosin/spec-tools "0.5.1"] is available but we use "0.5.0"-
Better error messages for bad
letksyntax by Erik Assum, fixes #354 -
:coercionapplies forcontextparameters too (not just childs) -
updated deps:
[metosin/muuntaja "0.3.3"] is available but we use "0.3.2"- route sequences also produce swagger docs.
dynamic-contextis removed in favor of:dynamic truemeta-data for contexts:
(require '[compojure.api.help :as help])
(help/help :meta :dynamic)
; :dynamic
;
; If set to to `true`, makes a `context` dynamic,
; e.g. body is evaluated on each request. NOTE:
; Vanilla Compojure has this enabled by default
; while compojure-api default to `false`, being
; much faster. For details, see:
;
; https://github.com/weavejester/compojure/issues/148
;
; (context "/static" []
; (if (= 0 (random-int 2))
; ;; mounting decided once
; (GET "/ping" [] (ok "pong")))
;
; (context "/dynamic" []
; :dynamic true
; (if (= 0 (random-int 2))
; ;; mounted for 50% of requests
; (GET "/ping" [] (ok "pong")))- You can now include sequences of routes in
routesandcontext:
(context "/api" []
(for [path ["/ping" "/pong"]]
(GET path [] (ok {:path path}))))- updated deps:
[metosin/ring-swagger "0.24.3"] is available but we use "0.24.2"-
ANYproduces swagger-docs for all methods, thanks to Anthony -
Updated deps:
[metosin/spec-tools "0.5.0"] is available but we use "0.4.0"- Stringify
:predunder Spec:problems, fixes #345 - Better error message if
:speccoercion is tried without required dependencies - Don't memoize keyword-specs for now - allow easier redefining
-
Aligned with the latest spec-tools:
[metosin/spec-tools "0.4.0"] -
To use Clojure 1.9 & Spec with Swagger, these need to be imported:
[org.clojure/clojure "1.9.0-beta2"]
[metosin/spec-tools "0.4.0"]- Support
ring.middleware.http-responseexception handling directly:
(require '[compojure.api.sweet :refer :all])
(require '[ring.util.http-response :as http])
(api
{:exceptions {:handlers {::http/response handle-thrown-http-exceptions-here}}
(GET "/throws" []
(http/bad-request! {:message "thrown response"})))- Use Muuntaja for all JSON transformations, drop direct dependency to Cheshire.
- Muuntaja
apiinstance (if not undefined, e.g.nil) is injected into:compojure.api.request/muuntajafor endpoints to use.path-forandpath-for*now use this to encode path-parameters.
(require '[compojure.api.sweet :refer :all])
(require '[compojure.api.request :as request])
(require '[muuntaja.core :as m])
(api
(GET "/ping" {:keys [::request/muuntaja]}
(ok {:json-string (slurp (m/encode muuntaja "application/json" [:this "is" 'JSON]))})))- FIXED: separate
Muuntaja-instance optins are merged correctly.
(require '[compojure.api.sweet :refer :all])
(require '[ring.util.http-response :refer [ok]])
(require '[metosin.transit.dates :as transit-dates])
(require '[muuntaja.core :as m])
(def muuntaja
(m/create
(-> muuntaja/default-options
(update-in
[:formats "application/transit+json"]
merge
{:decoder-opts {:handlers transit-dates/readers}
:encoder-opts {:handlers transit-dates/writers}}))))
(api
{:formats muuntaja}
(GET "/pizza" []
(ok {:now (org.joda.time.DateTime/now)})))- dropped dependencies:
[cheshire "5.7.1"]
[org.tobereplaced/lettercase "1.0.0"]- updated dependencies:
[potemkin "0.4.4"] is available but we use "0.4.3"
[metosin/ring-swagger "0.24.2"] is available but we use "0.24.1"
[metosin/spec-tools "0.4.0"] is available but we use "0.3.2"- drop direct support for
application/yaml&application/msgpack. If you want to add them back, you need to manually add the dependencies below and configure Muuntaja to handle those:
(require '[muuntaja.core :as muuntaja])
(require '[muuntaja.format.yaml :as yaml-format])
(require '[muuntaja.format.msgpack :as msgpack-format])
(api
{:formats (-> muuntaja/default-options
(yaml-format/with-yaml-format)
(msgpack-format/with-msgpack-format))}
...)- dropped dependencies:
[circleci/clj-yaml "0.5.6"]
[clojure-msgpack "1.2.0"]-
spec coericon also calls
s/unformafters/conform, e.g. specs like(s/or :int spec/int? :keyword spec/keyword?)work now too. -
updated dependencies:
[circleci/clj-yaml "0.5.6"] is available but we use "0.5.5"
[metosin/muuntaja "0.3.2"] is available but we use "0.3.1"
[ring/ring-core "1.6.2"] is available but we use "1.6.1"
[metosin/ring-swagger "0.24.1"] is available but we use "0.24.0"-
updated deps for the 1.*
-
BREAKING: in
compojure.api.swagger, theswagger-uiandswagger-docsnow take options map withpathkey instead of separate optional path & vararg opts.- normally you would use swagger api-options or
swagger-routesand thus be unaffected of this.
- normally you would use swagger api-options or
-
updated dependencies:
[prismatic/plumbing "0.5.4"] is available but we use "0.5.3"
[compojure "1.6.0"] is available but we use "1.5.2"
[prismatic/schema "1.1.6"] is available but we use "1.1.3"
[ring-middleware-format "0.7.2"] is available but we use "0.7.0"
[metosin/ring-http-response "0.9.0"] is available but we use "0.8.1"
[metosin/ring-swagger "0.24.1"] is available but we use "0.22.14"-
Spec coercion endpoints produce now Swagger2 data
- thanks to latest spec-tools
-
To use Clojure 1.9 & Spec with Swagger, these need to be imported:
[org.clojure/clojure "1.9.0-alpha17"]
[metosin/spec-tools "0.3.0"]- To use Clojure 1.8 & Spec with Swagger, these need to be imported:
[org.clojure/clojure "1.8.0"]
[metosin/spec-tools "0.3.0" :exclusions [org.clojure/spec.alpha]]
[clojure-future-spec "1.9.0-alpha17"]- If the dependencies are found, the following entry should appear on log:
INFO :spec swagger generation enabled in compojure.api
- updated deps:
[metosin/spec-tools "0.3.0"] is available but we use "0.2.2"
- Schema coercion errors have the :schema as
pr-strvalue. resourcebody-params are associated over existing instead of merged. e.g. extra params are really stripped off.
-
Update to latest Muuntaja.
- by default, allow empty input body for all formats
- see changelog
-
updated deps:
[metosin/muuntaja "0.3.1"] is available but we use "0.2.2"
- move
compojure.api.requestback tosrc.
- BREAKING: Simplified pluggable coercion.
- NO SWAGGER-DOCS YET, see https://github.com/metosin/spec-swagger
- guide in wiki: https://github.com/metosin/compojure-api/wiki/Coercion
- injected in request under
:compojure.api.request/coercion - new namespace
compojure.api.coercion, replacingcompojure.api.coerce. :coercioncan be set toapi,context, endpoint macros or aresource. It can be either:- something satisfying
compojure.api.coercion.core/Coercion - a Keyword for looking up a predefined
Coercionviacompojure.api.coercion.core/named-coercionmultimethod.
- something satisfying
coercionis stored in Route:info- signature of
Coercion:
(defprotocol Coercion
(get-name [this])
(get-apidocs [this spec data])
(encode-error [this error])
(coerce-request [this model value type format request])
(coerce-response [this model value type format request])):schema(default) resolves tocompojure.api.coercion.schema/SchemaCoercion:specresolves tocompojure.api.coercion.spec/SpecCoercion- automatically available if spec-tools is found in classpath
- to enable runtime conforming, use Spec Records
- works both with vanilla specs & data-specs
nilremoves the coercion (was:nilor(constantly nil)).
(require '[compojure.api.sweet :refer :all])
(require '[clojure.spec.alpha :as s])
(require '[spec-tools.spec :as spec])
(s/def ::id spec/int?)
(s/def ::name spec/string?)
(s/def ::description spec/string?)
(s/def ::type spec/keyword?)
(s/def ::new-pizza (s/keys :req-un [::name ::type] :opt-un [::description]))
(s/def ::pizza (s/keys :req-un [::id ::name ::type] :opt-un [::description]))
(resource
{:coercion :spec
:summary "a spec resource, no swagger yet"
:post {:parameters {:body-params ::new-pizza}
:responses {200 {:schema ::pizza}}
:handler (fn [{new-pizza :body-params}]
(ok (assoc new-pizza :id 1)))}})(require '[spec-tools.data-spec :as ds])
(s/def ::id spec/int?)
(context "/spec" []
:coercion :spec
(POST "/pizza" []
:summary "a spec endpoint"
:return ::pizza
:body [new-pizza ::new-pizza]
(ok (assoc new-pizza :id 1)))
(POST "/math/:x" []
:summary "a spec endpoint"
:return {:total int?}
:path-params [x :- spec/int?]
:query-params [y :- spec/int?,
{z :- spec/int? 0}]
(ok {:total (+ x y z)})))- To use Clojure 1.9 & Spec, these need to be imported:
[org.clojure/clojure "1.9.0-alpha17"]
[metosin/spec-tools "0.2.2"]- To use Clojure 1.8 & Spec, these need to be imported:
[org.clojure/clojure "1.8.0"]
[metosin/spec-tools "0.2.2" :exclusions [org.clojure/spec.alpha]]
[clojure-future-spec "1.9.0-alpha17"]-
BREAKING: Clojure 1.7.0 is no longer supported (no back-port for
clojure.spec). -
use ClassLoader -scoped Schema memoization instead of api-scoped - same for anonymous map specs
-
:body-paramsis available for exception handlers, fixes #306 & #313 -
BREAKING: Restructuring internal key changes in
compojure.api.meta::swaggeris removed in favor of:info.- swagger-data is pushed to
[:info :public]instead of[:swagger] - top-level
:infocan contain::static-context?->trueif thecontextis internally optimized as static:name, route name:coercion, the defined coercion
- More descriptive error messages, fixes #304 and #306:
- when request or response validation fails, more info is provided both to exception hanlders and via default implementations to external clients:
(let [app (GET "/" []
:return {:x String}
(ok {:kikka 2}))]
(try
(app {:request-method :get, :uri "/"})
(catch Exception e
(ex-data e))))
; {:type :compojure.api.exception/response-validation,
; :validation :schema,
; :in [:response :body],
; :schema {:x java.lang.String},
; :errors {:x missing-required-key,
; :kikka disallowed-key},
; :response {:status 200,
; :headers {},
; :body {:kikka 2}}}(let [app (GET "/" []
:query-params [x :- String]
(ok))]
(try
(app {:request-method :get, :uri "/" :query-params {:x 1}})
(catch Exception e
(ex-data e))))
; {:type :compojure.api.exception/request-validation,
; :validation :schema,
; :value {:x 1},
; :in [:request :query-params],
; :schema {Keyword Any, :x java.lang.String},
; :errors {:x (not (instance? java.lang.String 1))},
; :request {:request-method :get,
; :uri "/",
; :query-params {:x 1},
; :route-params {},
; :params {},
; :compojure/route [:get "/"]}}-
Introduce
dynamic-contextthat works likecontextbefore the fast context optimization (#253).- If you build routes dynamically inside
context, they will not work as intended. If you need this, replacecontextwithdynamic-context. - See issue #300.
For example:
- If you build routes dynamically inside
;; compojure-api 1.1
(context "/static" []
(if (its-noon?)
(GET "/noon-route" [] (ok "it's noon")))
;; compojure-api 1.2:
(dynamic-context "/static" []
(if (its-noon?)
(GET "/noon-route" [] (ok "it's noon")))- Remove restructuring migration helpers for
1.0.0(for:parametersand:middlewares)
-
BREAKING:
resourcefunction is always 1-arity, options and info are merged. -
resourcecan have:middlewareon both top-level & method-level.- top-level mw are applied first if the resource can handle the request
- method-level mw are applied second if the method matches
(def mw [handler value]
(fn [request]
(println value)
(handler request)))
(resource
{:middleware [[mw :top1] [mw :top2]]
:get {:middleware [[mw :get1] [mw :get2]]}
:post {:middleware [[mw :post1] [mw :post2]]}
:handler (constantly (ok))})- updated deps:
[prismatic/schema "1.1.6"] is available but we use "1.1.5"- BREAKING:
resourceseparates 1-arity:handlerand 3-arity:async-handler. Rules:- if resource is called with 1-arity,
:handleris used, sent viacompojure.response/render - if resource is called with 3-arity,
:async-handleris used, with fallback to:handler.- sent via
compojure.response/sendso manifoldDeferredand core.asyncManyToManyChannelcan be returned.
- sent via
- if resource is called with 1-arity,
(require '[compojure.api.sweet :refer :all])
(require '[clojure.core.async :as a])
(require '[manifold.deferred :as d])
(resource
{:summary "async resource"
:get {:summary "normal ring async"
:async-handler (fn [request respond raise]
(future
(Thread/sleep 100)
(respond (ok {:hello "world"})))
nil)}
:put {:summary "core.async"
:handler (fn [request]
(a/go
(a/<! (a/timeout 100))
(ok {:hello "world"})))}
:post {:summary "manifold"
:handler (fn [request]
(d/future
(Thread/sleep 100)
(ok {:hello "world"})))}})- updated deps:
[ring/ring-core "1.6.1"] is available but we use "1.6.0"- depend directly on
[ring/ring-core "1.6.0"] compojure.api.coredepends oncompojure.api.async- both manifold
Deferredand core.asyncManyToManyChannelcan be returned from endpoints.
- both manifold
resourcenow supports async (3-arity) handlers as well.
(resource
{:parameters {:query-params {:x Long}}
:handler (fn [request respond raise]
(future
(res (ok {:total (-> request :query-params :x)})))
nil)})- updated deps:
[ring/ring-core "1.6.0"]
[cheshire "5.7.1"] is available but we use "5.7.0"
[compojure "1.6.0"] is available but we use "1.5.2"
[prismatic/schema "1.1.5"] is available but we use "1.1.4"
[prismatic/plumbing "0.5.4"] is available but we use "0.5.3"
[metosin/ring-http-response "0.9.0"] is available but we use "0.8.2"
[metosin/ring-swagger "0.24.0"] is available but we use "0.23.0"
[compojure "1.6.0"] is available but we use "1.6.0-beta3"- Use the latest Muuntaja.
- Test with
[org.clojure/clojure "1.9.0-alpha15"](requires Midje1.9.0-alpha6)
[metosin/muuntaja "0.2.1"] is available but we use "0.2.0-20170323.064148-15"-
Initial support for Async Ring, using CPS, manifold or core.async
- more info at https://github.com/metosin/compojure-api/wiki/Async
-
compojure.api.core/ring-handlerto turn a compojure-api route into a 1-arity function- can be passed into servers requiring handlers to be
Fn
- can be passed into servers requiring handlers to be
-
:paramsare populated correctly from:body-params -
Allow
nilpaths in routing, allows easy (static) conditional routing like:
(defn app [dev-mode?]
(api
(GET "ping" [] (ok "pong"))
(if dev-mode?
(GET "/drop-the-db" [] (ok "dropped")))))- Support
java.io.Fileas response type, mapping to file downloads- no response coercion
- fixes #259
(GET "/file" []
:summary "a file download"
:return java.io.File
:produces #{"image/png"}
(-> (io/resource "screenshot.png")
(io/input-stream)
(ok)
(header "Content-Type" "image/png"))))-
Fix help-for for some restructure methods #275 by Nicolás Berger
-
BREAKING: in
compojure.api.swagger, theswagger-uiandswagger-docsnow take options map withpathkey instead of separate optional path & vararg opts.- normally you would use swagger api-options or
swagger-routesand thus be unaffected of this.
- normally you would use swagger api-options or
-
BREAKING:
middlewareis removed because it dangerously applied the middleware even to requests that didn't match the contained routes. Newroute-middlewareonly applies middlewares when the request is matched against contained routes.route-middlewareis not exposed insweetnamespace but is available atcompojure.api.core
-
Updated deps:
[metosin/muuntaja "0.2.0-20170323.064148-15"] is available but we use "0.2.0-20170122.164054-8"
[prismatic/schema "1.1.4"] is available but we use "1.1.3"
[metosin/ring-swagger-ui "2.2.10"] is available but we use "2.2.8"
[metosin/ring-swagger "0.23.0"] is available but we use "0.22.14"
[metosin/ring-http-response "0.8.2"] is available but we use "0.8.1"- Class-based exception handling made easier, the
[:exceptions :handlers]options also allows exception classes as keys.- First do a
:type-lookup, then by Exception class and it's superclasses. - Fixes #266
- First do a
(api
{:exceptions
{:handlers
{::ex/default handle-defaults
java.sql.SQLException handle-all-sql-exceptions}}}
...)- Lovely inline-help,
compojure.api.help/help.
(require '[compojure.api.help :refer [help]])
(help)
; ------------------------------------------------------------
; Usage:
;
; (help)
; (help topic)
; (help topic subject)
;
; Topics:
;
; :meta
;
; Topics & subjects:
;
; :meta :body
; :meta :body-params
; :meta :coercion
; :meta :components
; :meta :consumes
; :meta :description
; :meta :form-params
; :meta :header-params
; :meta :middleware
; :meta :multipart-params
; :meta :name
; :meta :no-doc
; :meta :operationId
; :meta :path-params
; :meta :produces
; :meta :responses
; :meta :return
; :meta :summary
; :meta :swagger
; :meta :tags
(help/help :meta :middleware)
; ------------------------------------------------------------
;
; :middleware
;
; Applies the given vector of middleware to the route.
; Middleware is presented as data in a Duct-style form:
;
; 1) ring mw-function (handler->request->response)
;
; 2) mw-function and it's arguments separately - mw is
; created by applying function with handler and args
;
; (defn require-role [handler role]
; (fn [request]
; (if (has-role? request role)
; (handler request)
; (unauthorized))))
;
; (def require-admin (partial require-role :admin))
;
; (GET "/admin" []
; :middleware [require-admin]
; (ok))
;
; (GET "/admin" []
; :middleware [[require-role :admin]]
; (ok))
;
; (GET "/admin" []
; :middleware [#(require-admin % :admin)]
; (ok))
;- help can be of anything. contributing to help:
(defmethod help/help-for [:restructuring :query-params] [_ _]
(help/text
"Restructures query-params with plumbing letk notation.\n"
"Example: read x and optionally y (defaulting to 1)"
"from query parameters. Body of the endpoint sees the"
"coerced values.\n"
(help/code
"(GET \"/ping\""
" :query-params [x :- Long, {y :- Long 1}]"
" (ok (+ x y)))")))- Updated deps:
[metosin/muuntaja "0.2.0-20170130.142747-9"] is available but we use "0.2.0-20170122.164054-8"this is an alpha release, feedback welcome
- BREAKING: Requires Java 1.8 (as Muuntaja requires it)
- Fix Cider indentation for route macros, by Joe Littlejohn
- Restructuring
:bodydoes not keywordize all keys,- e.g. EDN & Transit keys are not transformed, JSON keys based on the JSON decoder settings (defaulting to
true).
- e.g. EDN & Transit keys are not transformed, JSON keys based on the JSON decoder settings (defaulting to
resourceundercontextrequires exact routing match, fixes #269- Endpoints can return
compojure.api.routes/Routes, returned routes don't commit to swagger-docs - as they can be generated at runtime - BREAKING: Better request & response coercion
- in
compojure.api.middleware, thedefault-coercion-matchersis removed in favour ofcreate-coercion&default-coercion-options - uses negotiated format information provided by Muuntaja, fixes #266
- old custom
coercionshould work as before, as the contract has not changed - Old defaults: coerce everything (request & response body) with
json-coercion-matcher - New defaults: see the table below:
- in
| Format | Request | Response |
|---|---|---|
application/edn |
validate | validate |
application/transit+json |
validate | validate |
application/transit+msgpack |
validate | validate |
application/json |
json-coercion-matcher |
validate |
application/msgpack |
json-coercion-matcher |
validate |
application/x-yaml |
json-coercion-matcher |
validate |
defaults as code:
(def default-coercion-options
{:body {:default (constantly nil)
:formats {"application/json" json-coercion-matcher
"application/msgpack" json-coercion-matcher
"application/x-yaml" json-coercion-matcher}}
:string string-coercion-matcher
:response {:default (constantly nil)
:formats {}}})to create a valid coercion (for api or to routes):
;; create (with defaults)
(mw/create-coercion)
(mw/create-coercion mw/default-coercion-options)
;; no response coercion
(mw/create-coercion (dissoc mw/default-coercion-options :response)
;; disable all coercion
nil
(mw/create-coercion nil)- Route-records printing is cleaned up
(context "/api" []
(GET "/ping" [] (ok))
(POST "/echo" []
:body [data {:name s/Str}]
:return {:name s/Str}
(ok data))
(context "/resource" []
(resource
{:get {:handler (constantly (ok))}})))
; #Route {:path "/api",
; :childs [#Route {:path "/ping"
; :method :get}
; #Route {:path "/echo",
; :method :post,
; :info {:parameters {:body {:name Str}},
; :responses {200 {:schema {:name Str}
; :description ""}}}}
; #Route {:path "/resource"
; :childs [#Route{:childs [#Route{:path "/"
; :method :get}]}]}]}- Updated deps:
[cheshire "5.7.0"] is available but we use "5.6.3"
[metosin/muuntaja "0.2.0-20170122.164054-8"] is available but we use "0.2.0-20161031.085120-3"
[metosin/ring-http-response "0.8.1"] is available but we use "0.8.0"
[metosin/ring-swagger "0.22.14"] is available but we use "0.22.12"
[metosin/ring-swagger-ui "2.2.8"] is available but we use "2.2.5-0"- BREAKING: use Muuntaja instead of ring-middleware-format, #255
for format negotiation, encoding and decoding.
- 4x more throughput on 1k JSON request-response echo
- api key
:formathas been deprecated (fails at api creation time), use:formatsinstead. It consumes either a Muuntaja instance, Muuntaja options map ornil(unmounts it). See how to configure Muuntaja how to use.
EXPERIMENTAL: fastcontexts, #253 - use static routes if acontextdoesn't do any lexical bindings- up to 4x faster
contextrouting.
- up to 4x faster
- Support delayed child route resolution.
- Removed pre 0.23.0 api option format assertions.
:middlewareforapi&api-middleware, run last just before the actual routes. Uses same syntax as with the routing macros.
(api
{:middleware [no-cache [wrap-require-role :user]]}
...)- Updated deps:
[metosin/muuntaja "0.2.0-SNAPSHOT"]
[metosin/ring-swagger "0.22.12"] is available but we use "0.22.11"- Removed deps:
[ring-middleware-format "0.7.0"]- Updated dependencies to avoid a path traversal vulnerability in Ring.
[compojure "1.5.2"] is available but we use "1.5.1"
[metosin/ring-http-response "0.8.1"] is available but we use "0.8.0"
[metosin/ring-swagger "0.22.14"] is available but we use "0.22.11"
[metosin/ring-swagger-ui "2.2.8"] is available but we use "2.2.5-0"- Fix
:header-paramswith resources, #254 - updated dependencies:
[frankiesardo/linked "1.2.9"] is available but we use "1.2.7"
[metosin/ring-swagger "0.22.11"] is available but we use "0.22.10"
[metosin/ring-swagger-ui "2.2.5-0"] is available but we use "2.2.2-0"-
Lot's of new swagger-bindings from Ring-swagger:
schema.core.defrecordorg.joda.time.LocalTime- primitive arrays, fixes #177
s/Anyin body generates empty object instead of nil
-
Bundled with latest swagger-ui
2.2.2-0 -
Updated deps:
[metosin/ring-swagger "0.22.10"] is available but we use "0.22.9"
[metosin/ring-swagger-ui "2.2.2-0"] is available but we use "2.2.1-0"-
Bundled with the latest Swagger-ui (2.2.1-0)
-
Updated deps:
[metosin/ring-swagger-ui "2.2.1-0"] is available but we use "2.1.4-0":content-typeof user-defined formats are pushed into Swagger:producesand:consumes, thanks to Waldemar.
(def custom-json-format
(ring.middleware.format-response/make-encoder cheshire.core/generate-string "application/vnd.vendor.v1+json"))
(api
{:format {:formats [custom-json-format :json :edn]}}
...)- New api-options
[:api :disable-api-middleware?]to disable the api-middleware completely. With this set,apionly produces the (reverse) route-tree + set's swagger stuff and sets schema coercions for the api.- Thanks to Alan Malloy for contributing!
(api
{:api {:disable-api-middleware? true}
;; Still available
:swagger {:ui "/api-docs"
:spec "/swagger.json"
:data {:info {:title "api"}}}}
...):datainswagger-routescan be overridden even if run outside ofapi:
(def app
(routes
(swagger-routes
{:ui "/api-docs"
:spec "/swagger.json"
:data {:info {:title "Kikka"}
:paths {"/ping" {:get {:summary "ping get"}}}}})
(GET "/ping" [] "pong"))))- unsetting
:formatoption inapi-middlewarecauses all format-middlewares not to mount - unsetting
:exceptionsoption inapi-middlewarecauses the exception handling to be disabled - unsetting
:coerciontranslates to same as setting it to(constantly nil)
(api
{:exceptions nil ;; disable exception handling
:format nil ;; disable ring-middleware-format
:coercion nil} ;; disable all schema-coercion
;; this will be really thrown
(GET "/throw" []
(throw (new RuntimeException))))- updated dependencies:
[prismatic/schema "1.1.3"] is available but we use "1.1.2"
[frankiesardo/linked "1.2.7"] is available but we use "1.2.6"-
fix reflection warning with logging, thanks to Matt K.
-
Empty contexts (
/) don't accumulate to the path, see weavejester/compojure#125 -
NOTE: update of
ring-http-responsehad a breaking change: -
updated dependencies:
[compojure "1.5.1"] is available but we use "1.5.0"
[metosin/ring-http-response "0.8.0"] is available but we use "0.7.0"
[cheshire "5.6.3"] is available but we use "5.6.1"- updated dependencies:
[prismatic/schema "1.1.2"] is available but we use "1.1.1"
[metosin/ring-http-response "0.7.0"] is available but we use "0.6.5"
[metosin/ring-swagger "0.22.9"] is available but we use "0.22.8"
[reloaded.repl "0.2.2"] is available but we use "0.2.1"
[peridot "0.4.4"] is available but we use "0.4.3"
[reloaded.repl "0.2.2"] is available but we use "0.2.1"-
Response headers are mapped correctly, fixes #232
-
updated dependencies:
[metosin/ring-swagger "0.22.8"] is available but we use "0.22.7"- Allow usage of run-time parameters with
:swagger.
(let [runtime-data {:x-name :boolean
:operationId "echoBoolean"
:description "Ehcoes a boolean"
:parameters {:query {:q s/Bool}}}]
(api
(GET "/route" []
:swagger runtime-data
(ok {:it "works"}))))- Copy & coerce compojure
:route-paramsinto:path-paramswith resources- Fixes #231.
(resource
{:parameters {:path-params {:id s/Int}}
:responses {200 {:schema s/Int}}
:handler (fnk [[:path-params id]]
(ok (inc id)))})- updated dependencies:
[prismatic/schema "1.1.1"] is available but we use "1.1.0"- BREAKING: Move
compojure.api.swgger/validatetocompojure.api.validator/validate. - BREAKING: If a
resourcedoesn't define a handler for a givenrequest-methodor for top-level, nil is returned (instead of throwing exeption) - BREAKING Resource-routing is done by
context. Trying to return acompojure.api.routing/Routefrom an endpoint likeANYwill throw descriptive (runtime-)exception.
(context "/hello" []
(resource
{:description "hello-resource"
:responses {200 {:schema {:message s/Str}}}
:post {:summary "post-hello"
:parameters {:body-params {:name s/Str}}
:handler (fnk [[:body-params name]]
(ok {:message (format "hello, %s!" name)}))}
:get {:summary "get-hello"
:parameters {:query-params {:name s/Str}}
:handler (fnk [[:query-params name]]
(ok {:message (format "hello, %s!" name)}))}}))- api-level swagger-options default to
{:ui nil, :spec nil}. Setting up just the spec or ui, doesn't automatically setup the other (like previously) - Strip nils from
:middleware, fixes #228 describeworks with anonymous body-schemas (via ring-swagger0.22.7), Fixes #168- Support compojure-api apps in Google App Engine by allowing scjsv to be excluded (uses json-schema-validator, which uses rogue threads):
[metosin/compojure-api "1.1.0" :exclusions [[metosin/scjsv]]]- updated dependencies:
[metosin/ring-swagger "0.22.7"] is available but we use "0.22.6"
[prismatic/plumbing "0.5.3"] is available but we use "0.5.2"
[cheshire "5.6.1"] is available but we use "5.5.0"- Parameter order is unreversed for fnk-style destructurings for small number of paramerers, fixes #224
- Moved internal coercion helpers from
compojure.api.metatocompojure.api.coerce. - New
compojure.api.resource/resource(also incompojure.api.sweet) for building resource-oriented services
(defn resource
"Creates a nested compojure-api Route from enchanced ring-swagger operations map and options.
By default, applies both request- and response-coercion based on those definitions.
Options:
- **:coercion** A function from request->type->coercion-matcher, used
in resource coercion for :body, :string and :response.
Setting value to `(constantly nil)` disables both request- &
response coercion. See tests and wiki for details.
Enchancements to ring-swagger operations map:
1) :parameters use ring request keys (query-params, path-params, ...) instead of
swagger-params (query, path, ...). This keeps things simple as ring keys are used in
the handler when destructuring the request.
2) at resource root, one can add any ring-swagger operation definitions, which will be
available for all operations, using the following rules:
2.1) :parameters are deep-merged into operation :parameters
2.2) :responses are merged into operation :responses (operation can fully override them)
2.3) all others (:produces, :consumes, :summary,...) are deep-merged by compojure-api
3) special key `:handler` either under operations or at top-level. Value should be a
ring-handler function, responsible for the actual request processing. Handler lookup
order is the following: operations-level, top-level, exception.
4) request-coercion is applied once, using deep-merged parameters for a given
operation or resource-level if only resource-level handler is defined.
5) response-coercion is applied once, using merged responses for a given
operation or resource-level if only resource-level handler is defined.
Note: Swagger operations are generated only from declared operations (:get, :post, ..),
despite the top-level handler could process more operations.
Example:
(resource
{:parameters {:query-params {:x Long}}
:responses {500 {:schema {:reason s/Str}}}
:get {:parameters {:query-params {:y Long}}
:responses {200 {:schema {:total Long}}}
:handler (fn [request]
(ok {:total (+ (-> request :query-params :x)
(-> request :query-params :y))}))}
:post {}
:handler (constantly
(internal-server-error {:reason \"not implemented\"}))})"
([info]
(resource info {}))
([info options]
(let [info (merge-parameters-and-responses info)
root-info (swaggerize (root-info info))
childs (create-childs info)
handler (create-handler info options)]
(routes/create nil nil root-info childs handler))))- updated dependencies:
[compojure "1.5.0"] is available but we use "1.4.0"
[prismatic/schema "1.1.0"] is available but we use "1.0.5"
[metosin/ring-swagger "0.22.6"] is available but we use "0.22.4"- For response coercion, the original response is available in
ex-dataunder:response. This can be used in logging, "what did the route try to return". Thanks to Tim Gilbert. - Response coercion uses the
:defaultcode if available and response code doesn't match
(GET "/" []
:responses {200 {:schema {:ping s/Str}}
:default {:schema {:error s/int}}}
...)- updated dependencies:
[prismatic/schema "1.0.5"] is available but we use "1.0.4"- Swagger-routes mounted via api-options are mounted before other routes, fixes #218
- Routes are now resolved also from from Vars, fixes #219
- Better handling of
:basePathwithswagger-routes, thanks to Hoxu. - Updated dependencies:
[metosin/ring-swagger "0.22.4"] is available but we use "0.22.3"- Move from compile-time to runtime route resolution.
- Most of the internal macro magic has been vaporized
- Uses internally (invokable) Records & Protocols, allowing easier integration to 3rd party libs like Liberator
- even for large apps (100+ routes), route compilation takes now millis, instead of seconds
- sub-routes can be created with normal functions (or values), making it easier to:
- pass in app-level dependencies from libs like Component
- reuse shared request-handling time parameters like path-parameters and authorization info
(defn more-routes [db version]
(routes
(GET "/version" []
(ok {:version version}))
(POST "/thingie" []
(ok (thingie/create db)))))
(defn app [db]
(api
(context "/api/:version" []
:path-params [version :- s/Str]
(more-routes db version)
(GET "/kikka" []
(ok "kukka")))))-
BREAKING Vanilla Compojure routes will not produce any swagger-docs (as they do not satisfy the
Routingprotocol. They can still be used for handling request, just without docs.- a new api-level option
[:api :invalid-routes-fn]to declare how to handle routes not satisfying theRoutingprotocol. Default implementation logs invalid routes as WARNINGs.
- a new api-level option
-
BREAKING compojure.core imports are removed from
compojure.api.sweet:let-request,routing,wrap-routes
-
BREAKING Asterix (
*) is removed from route macro & function names, as there is no reason to mix compojure-api & compojure route macros.GET*=>GETANY*=>ANYHEAD*=>HEADPATCH*=>PATCHDELETE*=>DELETEOPTIONS*=>OPTIONSPOST*=>PUTcontext*=>contextdefroutes*=>defroutes
-
BREAKING
swagger-docsandswagger-uiare no longer incompojure.api.sweet- Syntax was hairy and when configuring the spec-url it needed to be set to both in order to work
- In future, there are multiple ways of setting the swagger stuff:
- via api-options
:swagger(has no defaults) - via
swagger-routesfunction, mounting both theswagger-uiandswagger-docsand wiring them together- by default, mounts the swagger-ui to
/and the swagger-spec to/swagger.json
- by default, mounts the swagger-ui to
- via the old
swagger-ui&swagger-docs(need to be separately imported fromcompojure.api.swagger). - see https://github.com/metosin/compojure-api/wiki/Swagger-integration for details
- via api-options
(defapi app
(swagger-routes)
(GET "/ping" []
(ok {:message "pong"})))
(defapi app
{:swagger {:ui "/", :spec "/swagger.json"}}
(GET "/ping" []
(ok {:message "pong"})))-
BREAKING: api-level coercion option is now a function of
request => type => matcheras it is documented. Previously required atype => matchermap. Options are checked againsttype => matchercoercion input, and a descriptive error is thrown when api is created with the old options format. -
BREAKING: Renamed
middlewarestomiddlewareand:middlewareskey (restructuring) to:middleware- will break at macro-expansion time with helpful exception
-
BREAKING: Middleware must be defined as data: both middleware macro and :middleware restructuring take a vector of middleware containing either
- a) fully configured middleware (function), or
- b) a middleware templates in form of
[function args] - You can also use anonymous or lambda functions to create middleware with correct parameters,
these are all identical:
[[wrap-foo {:opts :bar}]][#(wrap-foo % {:opts :bar})][(fn [handler] (wrap-foo handler {:opts :bar}))]
- Similar to duct
-
BREAKING: (Custom restructuring handlers only)
:parameterskey used byrestructure-paramhas been renamed to:swagger.- will break at macro-expansion time with helpful exception
-
BREAKING
public-resource-routes&public-resourcesare removed fromcompojure.api.middleware. -
BREAKING:
compojure.api.legacynamespace has been removed.
https://github.com/metosin/compojure-api/wiki/Migration-Guide-to-1.0.0
-
Additional route functions/macros in
compojure.api.core:routes&letroutes, just like in the Compojure, but supportingRoutingundocumented- works just likeroutesbut without any route definitions. Can be used to wrap legacy routes which setting the api option to fail on missing docs.
-
top-level
apiis now just function, not a macro. It takes an optional options maps and a top-level route function. -
Coercer cache is now at api-level with 10000 entries.
-
Code generated from restructured route macros is much cleaner now
-
Coercion is on by default for standalone (apiless) endpoints.
(fact "coercion is on for apiless routes"
(let [route (GET "/x" []
:query-params [x :- Long]
(ok))]
(route {:request-method :get :uri "/x" :query-params {}}) => throws))- Removed deps:
[backtick "0.3.3"]-
Fixed path parameter handling in cases where path parameter is followed by an extension (#196, metosin/ring-swagger#82)
-
Added
compojure.api.exception/with-logginghelper to add logging to exception handlers.- Check extended wiki guide on exception handling
-
Updated deps:
[metosin/ring-swagger "0.22.3"] is available- Updated deps:
[metosin/ring-swagger "0.22.2"] is available
[metosin/ring-swagger-ui "2.1.4-0"] is available
[potemkin "0.4.3"] is available-
coercer-cache is now per Route instead beeing global and based on a FIFO size 100 cache. Avoids potential memory leaks when using anonymous coercion matchers (which never hit the cache).
-
Updated deps:
[prismatic/schema "1.0.4"] is available but we use "1.0.3"- Memoize coercers (for
schema&matcher-input) for better performance.- Tests show 0-40% lower latency, depending on input & output schema complexity.
- Tested by sending json-strings to
apiand reading json-string out. - Measured a 80% lower latency with a real world large Schema.
- Updated deps:
[potemkin "0.4.2"] is available but we use "0.4.1"- uses
[Ring-Swagger "0.22.1"] clojure.tools.loggingis used with default uncaugt exception handling if it's found on the classpath. Fixes #172.- Both
apianddefapiproduce identical swagger-docs. Fixes #159 - allow any swagger data to be overriden at runtime either via swagger-docs or via middlewares. Fixes #170.
[metosin/ring-swagger "0.22.1"] is available but we use "0.22.0"
[metosin/ring-swagger-ui "2.1.3-4"] is available but we use "2.1.3-2"
[prismatic/plumbing "0.5.2] is available but we use "0.5.1"- BREAKING: Dropped support for Clojure 1.6
- BREAKING: Supports and depends on Schema 1.0.
- BREAKING:
ring-middleware-formataccepts transit options in a new format:
;; pre 0.24.0:
(api
{:format {:response-opts {:transit-json {:handlers transit/writers}}
:params-opts {:transit-json {:options {:handlers transit/readers}}}}}
...)
;; 0.24.0 +
(api
{:format {:response-opts {:transit-json {:handlers transit/writers}}
:params-opts {:transit-json {:handlers transit/readers}}}}
...)- Uses upstream ring-middleware-format instead of Metosin fork.
- Uses now linked instead of ordered for maps where order matters.
swagger-uinow supports passing arbitrary options toSwaggerUI(metosin/ring-swagger#67).
- Updated deps:
[prismatic/schema "1.0.3"] is available but we use "0.4.4"
[prismatic/plumbing "0.5.1] is available but we use "0.4.4"
[metosin/schema-tools "0.7.0"] is available but we use "0.5.2"
[metosin/ring-swagger "0.22.0"] is available but we use "0.21.0"
[metosin/ring-swagger-ui "2.1.3-2"] is available but we use "2.1.2"- Routes are kept in order for swagger docs, Fixes #138.
- Ring-swagger 0.21.0
- BREAKING: new signature for dispatching custom JSON Schema transformations, old signature will break (nicely at compile-time), see Readme for details.
- Support for collections in query parameters. E.g.
:query-params [x :- [Long]]& url?x=1&x=2&x=3should result inxbeing[1 2 3].
- BREAKING:
:validation-errors :error-handler,:validation-errors :catch-core-errors?and:exceptions :exception-handleroptions have been removed.- These have been replaced with general
:exceptions :handlersoptions. - Fails nicely at compile-time
- BREAKING: New handler use different arity than old handler functions.
- new arguments: Exception, ex-info and request.
- These have been replaced with general
- Move
contextfromcompojure.api.sweettocompojure.api.legacy. Usecontext*instead. - Updated deps:
[metosin/ring-swagger "0.21.0-SNAPSHOT"] is available but we use "0.20.4"
[compojure "1.4.0"] is available but we use "1.3.4"
[prismatic/schema "0.4.4"] is available but we use "0.4.3"
[metosin/ring-http-response "0.6.5"] is available but we use "0.6.3"
[metosin/schema-tools "0.5.2"] is available but we use "0.5.1"
[metosin/ring-swagger-ui "2.1.2"] is available but we use "2.1.5-M2"
[peridot "0.4.1"] is available but we use "0.4.0"- fixes 150
[metosin/ring-http-response "0.6.3"] is available but we use "0.6.2"
[midje "1.7.0"] is available but we use "1.7.0-SNAPSHOT"-
Optional integration with Component. Use either
:components-option ofapi-middlewareorwrap-components-middleware to associate the components with your API. Then you can use:components-restructuring to destructure your components using letk syntax. -
fix for #123
-
support for pluggable coercion, at both api-level & endpoint-level with option
:coercion. See thethe tests.- coercion is a function of type -
ring-request->coercion-type->coercion-matcherallowing protocol-based coercion in the future ** BREAKING**: if you have created custom restructurings usingsrc-coerce, they will break (nicely at compile-time)
- coercion is a function of type -
-
new restucturing
:swaggerjust for swagger-docs. Does not do any coercion.
(GET* "/documented" []
:swagger {:responses {200 {:schema User}
404 {:schema Error
:description "Not Found"} }
:paramerers {:query {:q s/Str}
:body NewUser}}}
...)[cheshire "5.5.0"] is available but we use "5.4.0"
[backtick "0.3.3"] is available but we use "0.3.2"
[lein-ring "0.9.6"] is available but we use "0.9.4":multipart-paramsnow sets:consumes ["multipart/form-data"]and:form-paramssets:consumes ["application/x-www-form-urlencoded"]- experimental: File upload support using
compojure.api.uploadnamespace.
(POST* "/upload" []
:multipart-params [file :- TempFileUpload]
:middlewares [wrap-multipart-params]
(ok (dissoc file :tempfile))))- breaking: use plain Ring-Swagger 2.0 models with
:responses. A helpfulIllegalArgumentExceptionwill be thrown at compile-time with old models. - new way:
:responses {400 {:schema ErrorSchema}}
:responses {400 {:schema ErrorSchema, :description "Eror"}}- allow configuring of Ring-Swagger via
api-middlewareoptions with key:ring-swagger:
(defapi app
{:ring-swagger {:ignore-missing-mappings? true}})
(swagger-docs)
(swagger-ui)
...)- Bidirectinal routing, inspired by bidi - named routes &
path-for:
(fact "bidirectional routing"
(let [app (api
(GET* "/api/pong" []
:name :pong
(ok {:pong "pong"}))
(GET* "/api/ping" []
(moved-permanently (path-for :pong))))]
(fact "path-for resolution"
(let [[status body] (get* app "/api/ping" {})]
status => 200
body => {:pong "pong"}))))- a validator for the api
(require '[compojure.api.sweet :refer :all])
(require '[compojure.api.swagger :refer [validate])
(defrecord NonSwaggerRecord [data])
(def app
(validate
(api
(swagger-docs)
(GET* "/ping" []
:return NonSwaggerRecord
(ok (->NonSwaggerRecord "ping"))))))
; clojure.lang.Compiler$CompilerException: java.lang.IllegalArgumentException:
; don't know how to create json-type of: class compojure.api.integration_test.NonSwaggerRecord- updated dependencies:
[metosin/ring-swagger "0.20.4"] is available but we use "0.20.3"
[metosin/ring-http-response "0.6.2"] is available but we use "0.6.1"
[metosin/ring-swagger-ui "2.1.5-M2"]
[prismatic/plumbing "0.4.4"] is available but we use "0.4.3"
[prismatic/schema "0.4.3"] is available but we use "0.4.2"- response descriptions can be given also with run-time meta-data (
with-meta), fixes #96- in next MINOR version, we'll switch to (Ring-)Swagger 2.0 format.
(context* "/responses" []
:tags ["responses"]
(GET* "/" []
:query-params [return :- (s/enum :200 :403 :404)]
:responses {403 ^{:message "spiders?"} {:code s/Str} ; old
404 (with-meta {:reason s/Str} {:message "lost?"})} ; new
:return Total
:summary "multiple returns models"
(case return
:200 (ok {:total 42})
:403 (forbidden {:code "forest"})
:404 (not-found {:reason "lost"}))))- welcome
compojure.api.core/api, the work-horse behindcompojure.api.core/defapi. - lexically bound route-trees, generated by
api, pushed to request via ring-swagger middlewares.- no more
+compojure-api-routes+littering the handler namespaces.
- no more
- fixes #101
- fixes #102
- update dependencies:
[metosin/ring-swagger "0.20.3"] is available but we use "0.20.2"
[prismatic/plumbing "0.4.3"] is available but we use "0.4.2"
[peridot "0.4.0"] is available but we use "0.3.1"
[compojure "1.3.4"] is available but we use "1.3.3"
[lein-ring "0.9.4"] is available but we use "0.9.3"- use ring-swagger middleware swagger-data injection instead of own custom mechanism.
- fixed #98: 2.0 UI works when running with context on (Servlet-based) app-servers.
- Preserve response-schema names, fixes #93.
- updated dependencies:
[metosin/ring-swagger "0.20.2"] is available but we use "0.20.0"
[prismatic/schema "0.4.2"] is available but we use "0.4.1"-
New restructuring for
:no-doc(a boolean) - endpoints with this don't get api documentation. -
Fixed #42 -
defroutes*now does namespace resolution for the source used for route peeling and source linking (the macro magic) -
Fixed #91 -
defroutes*are now automatically accessed over a Var for better development flow. -
Fixed #89.
-
Fixed #82.
-
Fixed #71, ring-swagger-ui is now a dependency.
-
breaking
ring.swagger.json-schema/describeis now imported intocompojure.api.sweetfor easy use. If your code refers to it directly, you need remove the direct reference.
- Routes are collected always from the root (
defapiorcompojure.api.routes/api-rootwithin that) compojure.api.routes/with-routesis nowcompojure.api.routes/api-root- breaking requires the latest swagger-ui to work
[metosin/ring-swagger-ui "2.1.1-M2"]to get things pre-configured- or package
2.1.1-M2yourself from the source.
- breaking: api ordering is not implemented.
- breaking: restructuring
:nicknameis now:operationId - breaking: restructuring
:notesis now:description swagger-docsnow takes any valid Swagger Spec data in. Using old format gives a warning is to STDOUT.
(swagger-docs
{:info {:version "1.0.0"
:title "Sausages"
:description "Sausage description"
:termsOfService "http://helloreverb.com/terms/"
:contact {:name "My API Team"
:email "foo@example.com"
:url "http://www.metosin.fi"}
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}}
:tags [{:name "kikka", :description "kukka"}]})- Swagger-documentation default uri is changed from
/api/api-docsto/swagger.json. compojure.api.swagger/swaggeredis deprecated - not relevant with 2.0. Works, but prints out a warning to STDOUT ** in 2.0, apis are categorized by Tags, one can set them either to endpoints or to paths:
(GET* "/api/pets/" []
:tags ["pet"]
(ok ...))(context* "/api/pets" []
:tags ["pet"]
(GET* "/" []
:summary "get all pets"
(ok ...)))- updated deps:
[metosin/ring-swagger "0.20.0"] is available but we use "0.19.4"
[prismatic/schema "0.4.1"] is available but we use "0.4.0"[prismatic/plumbing "0.4.2"] is available but we use "0.4.1"
[prismatic/schema "0.4.1"] is available but we use "0.4.0"
[potemkin "0.3.13"] is available but we use "0.3.12"
[compojure "1.3.3"] is available but we use "1.3.2"
[metosin/ring-swagger "0.19.4"] is available but we use "0.19.3"- Compatibility with swagger-ui
2.1.0-M2-[metosin/ring-swagger-ui "2.1.0-M2-2] - updated deps:
[metosin/ring-swagger "0.19.3"] is available but we use "0.19.2"- avoid reflection fixes by Michael Blume
- one can now wrap body & response-models in predicates and get the swagger docs out:
:return (s/maybe User)
:responses {200 (s/maybe User)
400 (s/either Cat Dog)}- updated deps:
[metosin/ring-swagger "0.19.2"] is available but we use "0.19.1"- added destructuring for
:headers, thanks to tchagnon! :path-paramallows any keywords, needed for the partial parameter matching withcontext*- BREAKING: parameters are collected in (Ring-)Swagger 2.0 format, might break client-side
compojure.api.meta/restructure-paramdispatch functions - for the swagger documentation part. See https://github.com/metosin/ring-swagger/blob/master/test/ring/swagger/swagger2_test.clj & https://github.com/metosin/compojure-api/blob/master/src/compojure/api/meta.clj for examples of the new schemas. context*to allow setting meta-data to mid-routes. Mid-route meta-data are deep-merged into endpoint swagger-definitions at compile-time. At runtime, code is executed in place.
(context* "/api/:kikka" []
:summary "summary inherited from context"
:path-params [kikka :- s/Str] ; enforced here at runtime
:query-params [kukka :- s/Str] ; enforced here at runtime
(GET* "/:kakka" []
:path-params [kakka :- s/Str] ; enforced here at runtime
(ok {:kikka kikka
:kukka kukka
:kakka kakka})))- updated deps:
[prismatic/plumbing "0.4.1"] is available but we use "0.3.7"
[potemkin "0.3.12"] is available but we use "0.3.11"
[prismatic/schema "0.4.0"] is available but we use "0.3.7"
[metosin/ring-http-response "0.6.1"] is available but we use "0.6.0"
[metosin/ring-swagger "0.19.0"] is available but we use "0.18.1"
[lein-ring "0.9.3"] is available but we use "0.9.2"- Support passing options to specific format middlewares (merged into defaults):
(defapi app
{:format {:formats [:json-kw :yaml-kw :edn :transit-json :transit-msgpack]
:params-opts {}
:response-opts {}}
:validation-errors {:error-handler nil
:catch-core-errors? nil}
:exceptions {:exception-handler default-exception-handler}}
...)- import
compojure.core/wrap-routesintocompojure.api.sweet - BREAKING: in
compojure.api.middleware,ex-info-supportis now parameterizablewrap-exception- fixes #68
- Update dependencies
[prismatic/plumbing "0.3.7"] is available but we use "0.3.5"
[compojure "1.3.2"] is available but we use "1.3.1"
[prismatic/schema "0.3.7"] is available but we use "0.3.3"
[metosin/ring-swagger "0.18.0"] is available but we use "0.15.0"
[metosin/ring-http-response "0.6.0"] is available but we use "0.5.2"
[metosin/ring-middleware-format "0.6.0"] is available but we use "0.5.0"
- Depend on forked version of
ring-middleware-format- Transit support should now work
- If you are depending on ring-middleware-format directly, you'll want to either update your dependency or exclude one from Compojure-api
- Update dependencies:
[cheshire "5.4.0"] is available but we use "5.3.1"
[metosin/ring-swagger-ui "2.0.24"] is available but we use "2.0.17"
[lein-ring "0.9.0"] is available but we use "0.8.13"- fix #53
- update deps:
[compojure "1.3.1"] is available but we use "1.2.1"
[metosin/ring-swagger "0.15.0"] is available but we use "0.14.1"
[peridot "0.3.1"] is available but we use "0.3.0"- fix anonymous Body & Return model naming issue 56 by Michael Blume
- update deps:
[prismatic/schema "0.3.3"] is available but we use "0.3.2"
[metosin/ring-http-response "0.5.2"] is available but we use "0.5.1"- use
[org.tobereplaced/lettercase "1.0.0"]for camel-casing (see metosin/compojure-api-examples#1 (comment)) - updated deps:
[metosin/ring-swagger "0.14.1"] is available but we use "0.14.0"- support for
:form-parameters, thanks to Thomas Whitcomb - update deps:
[prismatic/plumbing "0.3.5"] is available but we use "0.3.3"
[potemkin "0.3.11"] is available but we use "0.3.8"
[compojure "1.2.1"] is available but we use "1.1.9"
[prismatic/schema "0.3.2"] is available but we use "0.2.6"
[metosin/ring-http-response "0.5.1"] is available but we use "0.5.0"
[metosin/ring-swagger "0.14.0"] is available but we use "0.13.0"
[lein-ring "0.8.13"] is available but we use "0.8.11"- Fixed #47:
:middlewaresbroke route parameters
- Compiled without AOT
- Removed
:yaml-in-htmland:clojurefrom default response formats
- Some cleaning
- Requires now Clojure 1.6.0 for
clojure.walk
- Requires now Clojure 1.6.0 for
- Support other formats in addition to JSON
- Uses the ring-middleware-format to parse requests and encode responses
- Fixes #43: Middlewares added to route with :middlewares shouldn't leak to other routes in same context anymore
- Update to latest
ring-swagger
- Update to latest
ring-swagger- Fixes #16: If Schema has many properties, they are now shown in correct order on Swagger-UI
hash-maploses the order if it has enough propertiesUse flatland.ordered.map/ordered-map when Schema has many properties and you want to keep the order intact(s/defschema Thingie (ordered-map :a String ...))
- Fixes #16: If Schema has many properties, they are now shown in correct order on Swagger-UI
- Use latest
ring-swagger :bodyand others no langer take description as third param, instead use:body [body (describe Schema "The description")]describeworks also for Java classes:query-params [x :- (describe Long "first-param")]- And inside defschema
(s/defschema Schema {:sub (describe [{:x Long :y String}] "Array of stuff")})
- return model coercion returns
500instead of400, thanks to @phadej! - added support for returning primitives, thanks to @phadej!
(GET* "/plus" []
:return Long
:query-params [x :- Long {y :- Long 1}]
:summary "x+y with query-parameters. y defaults to 1."
(ok (+ x y))):responsesrestructuring to (error) return codes and models, thanks to @phadej!
(POST* "/number" []
:return Total
:query-params [x :- Long y :- Long]
:responses {403 ^{:message "Underflow"} ErrorEnvelope}
:summary "x-y with body-parameters."
(let [total (- x y)]
(if (>= total 0)
(ok {:total (- x y)})
(forbidden {:message "difference is negative"}))))- support for
s/Uuidvia latestring-swagger. - fail-fast (with client-typos): remove default implementation from
compojure.api.meta/restructure-param
- restructure
:header-params(fixes #31) - remove vanilla compojure-examples, internal cleanup
- allow primitives as return types (with help of
[metosin/ring-swagger 0.10.2])- all primitives are supported when wrapped into sequences and sets
- directly, only
Stringis supported as Ring doesn't support others- in future, there could be a special return value coercer forcing all other primitives as Strings
- first take on removing the global route state => instead of global
swaggeratom, there is one defined+routes+var per namespace- requires a
compojure.api.core/with-routeson api root to generate and hold the+routes+(automatically bundled withdefapi)
- requires a
- update ring-swagger to
0.10.1to get support fors/Keywordas a nested schema key.
- possibly breaking change:
middlewaresmacro and:middlewaresrestructuring now use thread-first to apply middlewares - update ring-swagger to
0.9.1with support for vanillaschema.core/defschemaschemas- big internal cleanup, removing model var-resolutions, lot's of internal fns removed
- added
defroutestocompojure.api.legacy - removed defns from
compojure.api.common:->Long,fn->,fn->> - cleaner output from
compojure.api.meta/restructure(doesn't generate emptylets&letks)
- added
compojure.api.legacyns to have the old Compojure HTTP-method macros (GET,POST,...)
- Update dependencies:
[prismatic/plumbing "0.3.1"] is available but we use "0.2.2"
[compojure "1.1.8"] is available but we use "1.1.7"
[prismatic/schema "0.2.3"] is available but we use "0.2.2"
[metosin/ring-swagger "0.8.8"] is available but we use "0.8.7"
[peridot "0.3.0"] is available but we use "0.2.2"
- Really updated ring-swagger dependency as I forgot that last with previous release
- remove non-first trailing spaces from Compojure-routes for swagger-docs.
- updated dependencies:
[metosin/ring-swagger "0.8.7"][metosin/ring-swagger-ui "2.6.16-2"]
- Moved swagger-ui handler to ring-swagger
-
updated dependencies:
[compojure "1.1.7"][prismatic/schema "0.2.2"][metosin/ring-swagger "0.8.5"]
-
consumesandproducesare now feed toring-swaggerbased on the installed middlewares.
- fix for #19
- change signature of
restructure-paramto receive key, value and the accumulator. Remove the key from accumulator parameters by default. No more alpha. - separate restructuring into own namespace
meta - new:
:middlewaresrestructuring to support adding middlewares to routes:
(DELETE* "/user/:id" []
:middlewares [audit-support (for-roles :admin)]
(ok {:name "Pertti"})))- breaking change:
with-middlewareis renamed tomiddlewares& it applies middlewares in reverse order - more docs on creating own metadata DSLs
- use
clojure.walk16internally
- fixed #12
- added http-kit example
- renamed
clojure.walktoclojure.walk16 - writing routes to
swaggeratom happens now at runtime, not compile-time. Works with AOT.
- All
compojure.api.corerestructuring are now usingrestructure-parammultimethod to allow external extensions. ALPHA.
- FIXED #9
swaggeredresources are now collected in order
- fixed bug with missing
+compojure-api-request+when having both Compojure destructuring & Compojure-api destructuring in place - added support for
:body-params(with strict schema):
(POST* "/minus" []
:body-params [x :- Long y :- Long]
:summary "x-y with body-parameters"
(ok {:total (- x y)}))- update
ring-swaggerto0.8.4to get better basepath-resolution (with reverse-proxies)
- support for Schema-aware
:path-parametersandquery-parameters:
(GET* "/sum" []
:query-params [x :- Long y :- Long]
:summary "sums x & y query-parameters"
(ok {:total (+ x y)}))
(GET* "/times/:x/:y" []
:path-params [x :- Long y :- Long]
:summary "multiplies x & y path-parameters"
(ok {:total (* x y)}))swagger-uiindex-redirect work also under a context when running in an legacy app-server. Thanks to Juha Syrjälä for the PR.
- use
instanceof?to match records instead of=with class. Apps can now be uberwarred withlein ring uberwar.
- update
ring-swaggerto0.8.3, generate path-parameters on client side
- update
ring-swaggerto0.8.1, all JSON-schema generation now done there.
- coerce return values with smart destructuring, thanks to Arttu Kaipiainen.
- update
ring-http-responseto0.4.0 - handle json-parse-errors by returning JSON
- rewrite
compojure.api.core-integration-testusingperidot.core
- Swagger path resolution works now with Compojure regular expression matching in URL parameters. Thanks to Arttu Kaipiainen.
(context "/api" []
(GET* ["/item/:name" :name #"[a-z/]+"] [name] identity))- Sets really work now with smart destructuring of
GET*andPOST*. Addeds tests to verify.
- update
ring-swaggerto0.7.3 - initial support for smart query parameter destructuring (arrays and nested params don't get swagger-ui love yet - but work otherwise ok)
(GET* "/echo" []
:return Thingie
:query [thingie Thingie]
(ok thingie)) ;; here be coerced thingie- Breaking change:
compojure.api.routes/defroutesis nowcompojure.api.core/defroutes*to avoid namespace clashes & promote it's different. - FIXED #4
- reverted "Compojures args-vector is now optional with
compojure.api.coreweb methods"
- reverted "Compojures args-vector is now optional with
- removed the Compojure Var pimp. Extended meta-data syntax no longer works with vanilla Compojure but requires the extended macros from
compojure.api.core. - update to
Ring-Swaggerto0.7.2
- date-format can be overridden in the
json-response-support, thanks to Dmitry Balakhonskiy - Update
Ring-Swaggerto0.7.1giving support for nested Maps:
(defmodel Customer {:id String
:address {:street String
:zip Long
:country {:code Long
:name String}}})- schema-aware body destructuring with
compojure.api.coreweb methods does now automatic coercion for the body - Compojures args-vector is now optional with
compojure.api.coreweb methods
(POST* "/customer"
:return Customer
:body [customer Customer]
(ok customer))) ;; we have a coerced customer here- update
ring-swaggerto0.7.0- support for
schema/maybeandschema/both - consume
Date&DateTimeboth with and without milliseconds:"2014-02-18T18:25:37.456Z"&"2014-02-18T18:25:37Z"
- support for
- name-parameter of
swaggeredis stripped out of spaces.
- update
ring-swaggerto0.6.0- support for LocalDate.
- updated example to cover all the dates.
swaggereddoesn't have to contain container-element (contextetc.) within, endpoints are ok:
(swaggered "ping"
:description "Ping api"
(GET* "/ping" [] (ok {:ping "pong"})))- body parameter in
POST*andPUT*now allows model sequences:
(POST* "/pizzas" []
:body [pizzas [NewPizza] {:description "new pizzas"}]
(ok (add! pizzas)))- update
ring-swaggerto0.5.0to get support for Data & DateTime.
swaggeredcan now follow symbols pointing to acompojure.api.routes/defroutesroute definition to allow better route composition.compojure.api.sweetnow usescompojure.api.routes/defroutesinstead ofcompojure.core/defroutes
- Fixed JSON Array -> Clojure Set coercing with Strings
- Initial public version