diff --git a/CHANGELOG.md b/CHANGELOG.md index 14c79f32..dfccf21f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,29 @@ We use [Break Versioning][breakver]. The version numbers follow a `.kukka"})}}]] + {:data {:muuntaja m/instance + :coercion rcs/coercion + :middleware [muuntaja/format-middleware + rrc/coerce-exceptions-middleware + rrc/coerce-request-middleware + rrc/coerce-response-middleware]}}))) + +(jetty/run-jetty #'app {:port 3000, :join? false}) +``` + +Testing with [httpie](https://httpie.org/): + +```bash +> http POST :3000/math x:=1 y:=2 + +HTTP/1.1 200 OK +Content-Length: 11 +Content-Type: application/json; charset=utf-8 +Date: Wed, 22 Aug 2018 16:59:54 GMT +Server: Jetty(9.2.21.v20170120) + +{ + "total": 3 +} +``` + +```bash +> http :3000/xml + +HTTP/1.1 200 OK +Content-Length: 20 +Content-Type: text/xml +Date: Wed, 22 Aug 2018 16:59:58 GMT +Server: Jetty(9.2.21.v20170120) + +kukka +``` + + +## Changing default parameters + +The current JSON formatter used by `reitit` already have the option to parse keys as `keyword` which is a sane default in Clojure. However, if you would like to parse all the `double` as `bigdecimal` you'd need to change an option of the [JSON formatter](https://github.com/metosin/jsonista) + + +```clj +(def new-muuntaja-instance + (m/create + (assoc-in + m/default-options + [:formats "application/json" :decoder-opts :bigdecimals] + true))) + +``` + +Now you should change the `m/instance` installed in the router with the `new-muuntaja-instance`. + +You can find more options for [JSON](https://cljdoc.org/d/metosin/jsonista/0.2.5/api/jsonista.core#object-mapper) and [EDN]. + + +## Adding custom encoder + +The example below is from `muuntaja` explaining how to add a custom encoder to parse a `java.util.Date` instance. + +```clj + +(def muuntaja-instance + (m/create + (assoc-in + m/default-options + [:formats "application/json" :encoder-opts] + {:date-format "yyyy-MM-dd"}))) + +(->> {:value (java.util.Date.)} + (m/encode m "application/json") + slurp) +; => "{\"value\":\"2019-10-15\"}" + +``` + +## Adding all together + +If you inspect `m/default-options` it's only a map, therefore you can compose your new muuntaja instance with as many options as you need it. + +```clj +(def new-muuntaja + (m/create + (-> m/default-options + (assoc-in [:formats "application/json" :decoder-opts :bigdecimals] true) + (assoc-in [:formats "application/json" :encoder-opts :data-format] "yyyy-MM-dd")))) +``` diff --git a/doc/ring/default_middleware.md b/doc/ring/default_middleware.md index 99db660e..5dc1a33d 100644 --- a/doc/ring/default_middleware.md +++ b/doc/ring/default_middleware.md @@ -1,7 +1,7 @@ # Default Middleware ```clj -[metosin/reitit-middleware "0.3.10"] +[metosin/reitit-middleware "0.4.2"] ``` Any Ring middleware can be used with `reitit-ring`, but using data-driven middleware is preferred as they are easier to manage and in many cases, yield better performance. `reitit-middleware` contains a set of common ring middleware, lifted into data-driven middleware. @@ -23,91 +23,6 @@ Any Ring middleware can be used with `reitit-ring`, but using data-driven middle See [Exception Handling with Ring](exceptions.md). -## Content Negotiation - -Wrapper for [Muuntaja](https://github.com/metosin/muuntaja) middleware for content-negotiation, request decoding and response encoding. Takes explicit configuration via `:muuntaja` key in route data. Emit's [swagger](swagger.md) `:produces` and `:consumes` definitions automatically based on the Muuntaja configuration. - -Negotiates a request body based on `Content-Type` header and response body based on `Accept`, `Accept-Charset` headers. Publishes the negotiation results as `:muuntaja/request` and `:muuntaja/response` keys into the request. - -Decodes the request body into `:body-params` using the `:muuntaja/request` key in request if the `:body-params` doesn't already exist. - -Encodes the response body using the `:muuntaja/response` key in request if the response doesn't have `Content-Type` header already set. - -Expected route data: - -| key | description | -| -------------|-------------| -| `:muuntaja` | `muuntaja.core/Muuntaja` instance, does not mount if not set. - -```clj -(require '[reitit.ring.middleware.muuntaja :as muuntaja]) -``` - -* `muuntaja/format-middleware` - Negotiation, request decoding and response encoding in a single Middleware -* `muuntaja/format-negotiate-middleware` - Negotiation -* `muuntaja/format-request-middleware` - Request decoding -* `muuntaja/format-response-middleware` - Response encoding - -```clj -(require '[reitit.ring :as ring]) -(require '[reitit.ring.coercion :as rrc]) -(require '[reitit.coercion.spec :as rcs]) -(require '[ring.adapter.jetty :as jetty]) - -(def app - (ring/ring-handler - (ring/router - [["/math" - {:post {:summary "negotiated request & response (json, edn, transit)" - :parameters {:body {:x int?, :y int?}} - :responses {200 {:body {:total int?}}} - :handler (fn [{{{:keys [x y]} :body} :parameters}] - {:status 200 - :body {:total (+ x y)}})}}] - ["/xml" - {:get {:summary "forced xml response" - :handler (fn [_] - {:status 200 - :headers {"Content-Type" "text/xml"} - :body "kukka"})}}]] - {:data {:muuntaja m/instance - :coercion rcs/coercion - :middleware [muuntaja/format-middleware - rrc/coerce-exceptions-middleware - rrc/coerce-request-middleware - rrc/coerce-response-middleware]}}))) - -(jetty/run-jetty #'app {:port 3000, :join? false}) -``` - -Testing with [httpie](https://httpie.org/): - -```bash -> http POST :3000/math x:=1 y:=2 - -HTTP/1.1 200 OK -Content-Length: 11 -Content-Type: application/json; charset=utf-8 -Date: Wed, 22 Aug 2018 16:59:54 GMT -Server: Jetty(9.2.21.v20170120) - -{ - "total": 3 -} -``` - -```bash -> http :3000/xml - -HTTP/1.1 200 OK -Content-Length: 20 -Content-Type: text/xml -Date: Wed, 22 Aug 2018 16:59:58 GMT -Server: Jetty(9.2.21.v20170120) - -kukka -``` - ## Multipart Request Handling Wrapper for [Ring Multipart Middleware](https://github.com/ring-clojure/ring/blob/master/ring-core/src/ring/middleware/multipart_params.clj). Emits swagger `:consumes` definitions automatically. diff --git a/doc/ring/exceptions.md b/doc/ring/exceptions.md index 1d484799..58b16648 100644 --- a/doc/ring/exceptions.md +++ b/doc/ring/exceptions.md @@ -1,7 +1,7 @@ # Exception Handling with Ring ```clj -[metosin/reitit-middleware "0.3.10"] +[metosin/reitit-middleware "0.4.2"] ``` Exceptions thrown in router creation can be [handled with custom exception handler](../basics/error_messages.md). By default, exceptions thrown at runtime from a handler or a middleware are not caught by the `reitit.ring/ring-handler`. A good practise is a have an top-level exception handler to log and format the errors for clients. diff --git a/doc/ring/ring.md b/doc/ring/ring.md index 2c74eeac..2bb622aa 100644 --- a/doc/ring/ring.md +++ b/doc/ring/ring.md @@ -5,7 +5,7 @@ Read more about the [Ring Concepts](https://github.com/ring-clojure/ring/wiki/Concepts). ```clj -[metosin/reitit-ring "0.3.10"] +[metosin/reitit-ring "0.4.2"] ``` ## `reitit.ring/ring-router` diff --git a/doc/ring/swagger.md b/doc/ring/swagger.md index c7c240a5..a30226b5 100644 --- a/doc/ring/swagger.md +++ b/doc/ring/swagger.md @@ -1,7 +1,7 @@ # Swagger Support ``` -[metosin/reitit-swagger "0.3.10"] +[metosin/reitit-swagger "0.4.2"] ``` Reitit supports [Swagger2](https://swagger.io/) documentation, thanks to [schema-tools](https://github.com/metosin/schema-tools) and [spec-tools](https://github.com/metosin/spec-tools). Documentation is extracted from route definitions, coercion `:parameters` and `:responses` and from a set of new documentation keys. @@ -44,7 +44,7 @@ If you need to post-process the generated spec, just wrap the handler with a cus [Swagger-ui](https://github.com/swagger-api/swagger-ui) is a user interface to visualize and interact with the Swagger specification. To make things easy, there is a pre-integrated version of the swagger-ui as a separate module. ``` -[metosin/reitit-swagger-ui "0.3.10"] +[metosin/reitit-swagger-ui "0.4.2"] ``` `reitit.swagger-ui/create-swagger-ui-hander` can be used to create a ring-handler to serve the swagger-ui. It accepts the following options: diff --git a/doc/ring/transforming_middleware_chain.md b/doc/ring/transforming_middleware_chain.md index 7e7711f8..c182b43d 100644 --- a/doc/ring/transforming_middleware_chain.md +++ b/doc/ring/transforming_middleware_chain.md @@ -59,7 +59,7 @@ There is an extra option in ring-router (actually, in the underlying middleware- ### Printing Request Diffs ```clj -[metosin/reitit-middleware "0.3.10"] +[metosin/reitit-middleware "0.4.2"] ``` Using `reitit.ring.middleware.dev/print-request-diffs` transformation, the request diffs between each middleware are printed out to the console. To use it, add the following router option: diff --git a/examples/frontend-auth/project.clj b/examples/frontend-auth/project.clj index e9eff0f7..ae4c34fb 100644 --- a/examples/frontend-auth/project.clj +++ b/examples/frontend-auth/project.clj @@ -10,9 +10,9 @@ [ring "1.7.1"] [hiccup "1.0.5"] [org.clojure/clojurescript "1.10.439"] - [metosin/reitit "0.3.10"] - [metosin/reitit-schema "0.3.10"] - [metosin/reitit-frontend "0.3.10"] + [metosin/reitit "0.4.2"] + [metosin/reitit-schema "0.4.2"] + [metosin/reitit-frontend "0.4.2"] ;; Just for pretty printting the match [fipp "0.6.14"]] diff --git a/examples/frontend-controllers/project.clj b/examples/frontend-controllers/project.clj index e9eff0f7..ae4c34fb 100644 --- a/examples/frontend-controllers/project.clj +++ b/examples/frontend-controllers/project.clj @@ -10,9 +10,9 @@ [ring "1.7.1"] [hiccup "1.0.5"] [org.clojure/clojurescript "1.10.439"] - [metosin/reitit "0.3.10"] - [metosin/reitit-schema "0.3.10"] - [metosin/reitit-frontend "0.3.10"] + [metosin/reitit "0.4.2"] + [metosin/reitit-schema "0.4.2"] + [metosin/reitit-frontend "0.4.2"] ;; Just for pretty printting the match [fipp "0.6.14"]] diff --git a/examples/frontend-links/project.clj b/examples/frontend-links/project.clj index 64615c31..194b0ed0 100644 --- a/examples/frontend-links/project.clj +++ b/examples/frontend-links/project.clj @@ -10,9 +10,9 @@ [ring "1.7.1"] [hiccup "1.0.5"] [org.clojure/clojurescript "1.10.520"] - [metosin/reitit "0.3.10"] - [metosin/reitit-spec "0.3.10"] - [metosin/reitit-frontend "0.3.10"] + [metosin/reitit "0.4.2"] + [metosin/reitit-spec "0.4.2"] + [metosin/reitit-frontend "0.4.2"] ;; Just for pretty printting the match [fipp "0.6.14"]] diff --git a/examples/frontend-prompt/project.clj b/examples/frontend-prompt/project.clj index 64615c31..194b0ed0 100644 --- a/examples/frontend-prompt/project.clj +++ b/examples/frontend-prompt/project.clj @@ -10,9 +10,9 @@ [ring "1.7.1"] [hiccup "1.0.5"] [org.clojure/clojurescript "1.10.520"] - [metosin/reitit "0.3.10"] - [metosin/reitit-spec "0.3.10"] - [metosin/reitit-frontend "0.3.10"] + [metosin/reitit "0.4.2"] + [metosin/reitit-spec "0.4.2"] + [metosin/reitit-frontend "0.4.2"] ;; Just for pretty printting the match [fipp "0.6.14"]] diff --git a/examples/frontend-re-frame/project.clj b/examples/frontend-re-frame/project.clj index 29454d36..d6279663 100644 --- a/examples/frontend-re-frame/project.clj +++ b/examples/frontend-re-frame/project.clj @@ -1,7 +1,7 @@ (defproject frontend-re-frame "0.1.0-SNAPSHOT" :dependencies [[org.clojure/clojure "1.10.0"] [org.clojure/clojurescript "1.10.520"] - [metosin/reitit "0.3.10"] + [metosin/reitit "0.4.2"] [reagent "0.8.1"] [re-frame "0.10.6"]] diff --git a/examples/frontend/project.clj b/examples/frontend/project.clj index abbde5c3..a815f90c 100644 --- a/examples/frontend/project.clj +++ b/examples/frontend/project.clj @@ -10,9 +10,9 @@ [ring "1.7.1"] [hiccup "1.0.5"] [org.clojure/clojurescript "1.10.439"] - [metosin/reitit "0.3.10"] - [metosin/reitit-spec "0.3.10"] - [metosin/reitit-frontend "0.3.10"] + [metosin/reitit "0.4.2"] + [metosin/reitit-spec "0.4.2"] + [metosin/reitit-frontend "0.4.2"] ;; Just for pretty printting the match [fipp "0.6.14"]] diff --git a/examples/http-swagger/project.clj b/examples/http-swagger/project.clj index 5a5cce5d..e25386a3 100644 --- a/examples/http-swagger/project.clj +++ b/examples/http-swagger/project.clj @@ -3,5 +3,5 @@ :dependencies [[org.clojure/clojure "1.10.0"] [ring/ring-jetty-adapter "1.7.1"] [aleph "0.4.7-alpha5"] - [metosin/reitit "0.3.10"]] + [metosin/reitit "0.4.2"]] :repl-options {:init-ns example.server}) diff --git a/examples/http/project.clj b/examples/http/project.clj index ba93693e..d857a76d 100644 --- a/examples/http/project.clj +++ b/examples/http/project.clj @@ -5,5 +5,5 @@ [funcool/promesa "1.9.0"] [manifold "0.1.8"] [ring/ring-jetty-adapter "1.7.1"] - [metosin/reitit "0.3.10"]] + [metosin/reitit "0.4.2"]] :repl-options {:init-ns example.server}) diff --git a/examples/just-coercion-with-ring/project.clj b/examples/just-coercion-with-ring/project.clj index b206f131..f637fb77 100644 --- a/examples/just-coercion-with-ring/project.clj +++ b/examples/just-coercion-with-ring/project.clj @@ -2,4 +2,4 @@ :description "Reitit coercion with vanilla ring" :dependencies [[org.clojure/clojure "1.10.0"] [ring/ring-jetty-adapter "1.7.1"] - [metosin/reitit "0.3.10"]]) + [metosin/reitit "0.4.2"]]) diff --git a/examples/pedestal-swagger/project.clj b/examples/pedestal-swagger/project.clj index bb60d2f0..73ec70f5 100644 --- a/examples/pedestal-swagger/project.clj +++ b/examples/pedestal-swagger/project.clj @@ -3,6 +3,6 @@ :dependencies [[org.clojure/clojure "1.10.0"] [io.pedestal/pedestal.service "0.5.5"] [io.pedestal/pedestal.jetty "0.5.5"] - [metosin/reitit-pedestal "0.3.10"] - [metosin/reitit "0.3.10"]] + [metosin/reitit-pedestal "0.4.2"] + [metosin/reitit "0.4.2"]] :repl-options {:init-ns example.server}) diff --git a/examples/pedestal/project.clj b/examples/pedestal/project.clj index bb60d2f0..73ec70f5 100644 --- a/examples/pedestal/project.clj +++ b/examples/pedestal/project.clj @@ -3,6 +3,6 @@ :dependencies [[org.clojure/clojure "1.10.0"] [io.pedestal/pedestal.service "0.5.5"] [io.pedestal/pedestal.jetty "0.5.5"] - [metosin/reitit-pedestal "0.3.10"] - [metosin/reitit "0.3.10"]] + [metosin/reitit-pedestal "0.4.2"] + [metosin/reitit "0.4.2"]] :repl-options {:init-ns example.server}) diff --git a/examples/ring-example/project.clj b/examples/ring-example/project.clj index f5f5586b..63a920e9 100644 --- a/examples/ring-example/project.clj +++ b/examples/ring-example/project.clj @@ -2,5 +2,5 @@ :description "Reitit Ring App" :dependencies [[org.clojure/clojure "1.10.0"] [ring/ring-jetty-adapter "1.7.1"] - [metosin/reitit "0.3.10"]] + [metosin/reitit "0.4.2"]] :repl-options {:init-ns example.server}) diff --git a/examples/ring-integrant/project.clj b/examples/ring-integrant/project.clj index 7db05f24..a58b51a7 100644 --- a/examples/ring-integrant/project.clj +++ b/examples/ring-integrant/project.clj @@ -2,7 +2,7 @@ :description "Reitit Ring App with Integrant" :dependencies [[org.clojure/clojure "1.10.1"] [ring/ring-jetty-adapter "1.7.1"] - [metosin/reitit "0.3.10"] + [metosin/reitit "0.4.2"] [integrant "0.7.0"]] :main example.server :repl-options {:init-ns user} diff --git a/examples/ring-malli-swagger/project.clj b/examples/ring-malli-swagger/project.clj index b7d76aa5..5f742d20 100644 --- a/examples/ring-malli-swagger/project.clj +++ b/examples/ring-malli-swagger/project.clj @@ -2,6 +2,6 @@ :description "Reitit Ring App with Swagger" :dependencies [[org.clojure/clojure "1.10.0"] [ring/ring-jetty-adapter "1.7.1"] - [metosin/reitit "0.3.10"]] + [metosin/reitit "0.4.2"]] :repl-options {:init-ns example.server} :profiles {:dev {:dependencies [[ring/ring-mock "0.3.2"]]}}) diff --git a/examples/ring-spec-swagger/project.clj b/examples/ring-spec-swagger/project.clj index b7d76aa5..5f742d20 100644 --- a/examples/ring-spec-swagger/project.clj +++ b/examples/ring-spec-swagger/project.clj @@ -2,6 +2,6 @@ :description "Reitit Ring App with Swagger" :dependencies [[org.clojure/clojure "1.10.0"] [ring/ring-jetty-adapter "1.7.1"] - [metosin/reitit "0.3.10"]] + [metosin/reitit "0.4.2"]] :repl-options {:init-ns example.server} :profiles {:dev {:dependencies [[ring/ring-mock "0.3.2"]]}}) diff --git a/examples/ring-swagger/project.clj b/examples/ring-swagger/project.clj index 616d06f1..2b680269 100644 --- a/examples/ring-swagger/project.clj +++ b/examples/ring-swagger/project.clj @@ -2,5 +2,5 @@ :description "Reitit Ring App with Swagger" :dependencies [[org.clojure/clojure "1.10.0"] [ring/ring-jetty-adapter "1.7.1"] - [metosin/reitit "0.3.10"]] + [metosin/reitit "0.4.2"]] :repl-options {:init-ns example.server}) diff --git a/modules/reitit-core/project.clj b/modules/reitit-core/project.clj index 7c725bc7..521f8003 100644 --- a/modules/reitit-core/project.clj +++ b/modules/reitit-core/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit-core "0.3.10" +(defproject metosin/reitit-core "0.4.2" :description "Snappy data-driven router for Clojure(Script)" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" diff --git a/modules/reitit-core/src/reitit/trie.cljc b/modules/reitit-core/src/reitit/trie.cljc index 6eaa417f..c4622b53 100644 --- a/modules/reitit-core/src/reitit/trie.cljc +++ b/modules/reitit-core/src/reitit/trie.cljc @@ -22,7 +22,7 @@ (defprotocol Matcher (match [this i max path]) (view [this]) - (depth [this]) + (depth ^long [this]) (length [this])) (defprotocol TrieCompiler @@ -53,7 +53,7 @@ :else (recur (inc i)))))) (defn- -keyword [s] - (if-let [i (str/index-of s "/")] + (if-let [^long i (str/index-of s "/")] (keyword (subs s 0 i) (subs s (inc i))) (keyword s))) @@ -61,8 +61,8 @@ (let [bracket? (-> syntax (into-set) :bracket) colon? (-> syntax (into-set) :colon) -static (fn [from to] (if-not (= from to) [(subs s from to)])) - -wild (fn [from to] [(->Wild (-keyword (subs s (inc from) to)))]) - -catch-all (fn [from to] [(->CatchAll (keyword (subs s (inc from) to)))])] + -wild (fn [^long from to] [(->Wild (-keyword (subs s (inc from) to)))]) + -catch-all (fn [^long from to] [(->CatchAll (keyword (subs s (inc from) to)))])] (loop [ss nil, from 0, to 0] (if (= to (count s)) (concat ss (-static from to)) @@ -70,13 +70,13 @@ (cond (and bracket? (= \{ c)) - (let [to' (or (str/index-of s "}" to) (ex/fail! ::unclosed-brackets {:path s}))] + (let [^long to' (or (str/index-of s "}" to) (ex/fail! ::unclosed-brackets {:path s}))] (if (= \* (get s (inc to))) (recur (concat ss (-static from to) (-catch-all (inc to) to')) (long (inc to')) (long (inc to'))) (recur (concat ss (-static from to) (-wild to to')) (long (inc to')) (long (inc to'))))) (and colon? (= \: c)) - (let [to' (or (str/index-of s "/" to) (count s))] + (let [^long to' (or (str/index-of s "/" to) (count s))] (if (= 1 (- to' to)) (recur ss from (inc to)) (recur (concat ss (-static from to) (-wild to to')) (long to') (long to')))) @@ -115,7 +115,7 @@ (and (string? cp) (not= (count cp) (count p))) [(subs p (count cp))] (and (string? p) (not cp)) (-split p))) -postcut (fn [[p :as pps]] - (let [i (and p (str/index-of p "/"))] + (let [^long i (and p (str/index-of p "/"))] (if (and i (pos? i)) (concat [(subs p 0 i) (subs p i)] (rest pps)) pps))) @@ -128,7 +128,7 @@ (defn- -slice-end [x xs] (let [i (if (string? x) (str/index-of x "/"))] - (if (and (number? i) (pos? i)) + (if (and (number? i) (pos? ^long i)) (concat [(subs x i)] xs) xs))) @@ -227,11 +227,11 @@ (let [size (count path)] (reify Matcher (match [_ i max p] - (if-not (< max (+ i size)) + (if-not (< ^long max (+ ^long i size)) (loop [j 0] (if (= j size) - (match matcher (+ i size) max p) - (if (= (get p (+ i j)) (get path j)) + (match matcher (+ ^long i size) max p) + (if (= (get p (+ ^long i j)) (get path j)) (recur (inc j))))))) (view [_] [path (view matcher)]) (depth [_] (inc (depth matcher))) @@ -239,8 +239,8 @@ (wild-matcher [_ key end matcher] (reify Matcher (match [_ i max path] - (if (and (< i max) (not= (get path i) end)) - (loop [percent? false, j i] + (if (and (< ^long i ^long max) (not= (get path i) end)) + (loop [percent? false, j ^long i] (if (= max j) (if-let [match (match matcher max max path)] (assoc-param match key (decode path i max percent?))) @@ -257,7 +257,7 @@ (let [match (->Match params data)] (reify Matcher (match [_ i max path] - (if (<= i max) (assoc-param match key (decode path i max true)))) + (if (<= ^long i ^long max) (assoc-param match key (decode path i max true)))) (view [_] [key [data]]) (depth [_] 1) (length [_])))) @@ -271,7 +271,7 @@ (or (match (get matchers j) i max path) (recur (inc j)))))) (view [_] (mapv view matchers)) - (depth [_] (inc (apply max 0 (map depth matchers)))) + (depth [_] (inc ^long (apply max 0 (map depth matchers)))) (length [_])))) (-pretty [_ matcher] (view matcher)) diff --git a/modules/reitit-dev/project.clj b/modules/reitit-dev/project.clj index 7d9b928a..b06c9d57 100644 --- a/modules/reitit-dev/project.clj +++ b/modules/reitit-dev/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit-dev "0.3.10" +(defproject metosin/reitit-dev "0.4.2" :description "Snappy data-driven router for Clojure(Script)" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" diff --git a/modules/reitit-frontend/project.clj b/modules/reitit-frontend/project.clj index 914e7ebb..142d70a7 100644 --- a/modules/reitit-frontend/project.clj +++ b/modules/reitit-frontend/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit-frontend "0.3.10" +(defproject metosin/reitit-frontend "0.4.2" :description "Reitit: Clojurescript frontend routing core" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" diff --git a/modules/reitit-http/project.clj b/modules/reitit-http/project.clj index c094f54b..4cc25583 100644 --- a/modules/reitit-http/project.clj +++ b/modules/reitit-http/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit-http "0.3.10" +(defproject metosin/reitit-http "0.4.2" :description "Reitit: HTTP routing with interceptors" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" diff --git a/modules/reitit-interceptors/project.clj b/modules/reitit-interceptors/project.clj index 1f377990..5a2312b8 100644 --- a/modules/reitit-interceptors/project.clj +++ b/modules/reitit-interceptors/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit-interceptors "0.3.10" +(defproject metosin/reitit-interceptors "0.4.2" :description "Reitit, common interceptors bundled" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" diff --git a/modules/reitit-malli/project.clj b/modules/reitit-malli/project.clj index 7649f787..a75b99d0 100644 --- a/modules/reitit-malli/project.clj +++ b/modules/reitit-malli/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit-malli "0.3.10" +(defproject metosin/reitit-malli "0.4.2" :description "Reitit: Malli coercion" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" diff --git a/modules/reitit-malli/src/reitit/coercion/malli.cljc b/modules/reitit-malli/src/reitit/coercion/malli.cljc index 411843da..45124991 100644 --- a/modules/reitit-malli/src/reitit/coercion/malli.cljc +++ b/modules/reitit-malli/src/reitit/coercion/malli.cljc @@ -75,18 +75,18 @@ ;; swagger ;; -(defmulti extract-parameter (fn [in _] in)) +(defmulti extract-parameter (fn [in _ _] in)) -(defmethod extract-parameter :body [_ schema] - (let [swagger-schema (swagger/transform schema {:in :body, :type :parameter})] +(defmethod extract-parameter :body [_ schema options] + (let [swagger-schema (swagger/transform schema (merge options {:in :body, :type :parameter}))] [{:in "body" :name (:title swagger-schema "") :description (:description swagger-schema "") :required (not= :maybe (m/name schema)) :schema swagger-schema}])) -(defmethod extract-parameter :default [in schema] - (let [{:keys [properties required]} (swagger/transform schema {:in in, :type :parameter})] +(defmethod extract-parameter :default [in schema options] + (let [{:keys [properties required]} (swagger/transform schema (merge options {:in in, :type :parameter}))] (mapv (fn [[k {:keys [type] :as schema}]] (merge @@ -135,7 +135,7 @@ (if parameters {:parameters (->> (for [[in schema] parameters - parameter (extract-parameter in (compile schema))] + parameter (extract-parameter in (compile schema options) options)] parameter) (into []))}) (if responses @@ -148,14 +148,14 @@ (update $ :description (fnil identity "")) (if (:schema $) (-> $ - (update :schema compile) + (update :schema compile options) (update :schema swagger/transform {:type :schema})) $))]))})) (throw (ex-info (str "Can't produce Schema apidocs for " specification) {:type specification, :coercion :schema})))) - (-compile-model [_ model _] (compile model)) + (-compile-model [_ model _] (compile model options)) (-open-model [_ schema] schema) (-encode-error [_ error] (cond-> error @@ -165,9 +165,9 @@ (update :errors (partial map #(update % :schema edn/write-string opts)))) (seq error-keys) (select-keys error-keys))) (-request-coercer [_ type schema] - (-coercer (compile schema) type transformers :decode nil options)) + (-coercer (compile schema options) type transformers :decode nil options)) (-response-coercer [_ schema] - (let [schema (compile schema) + (let [schema (compile schema options) encoder (-coercer schema :body transformers :encode nil options)] (-coercer schema :response transformers :encode encoder options))))))) diff --git a/modules/reitit-middleware/project.clj b/modules/reitit-middleware/project.clj index e9ef28d0..67b29781 100644 --- a/modules/reitit-middleware/project.clj +++ b/modules/reitit-middleware/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit-middleware "0.3.10" +(defproject metosin/reitit-middleware "0.4.2" :description "Reitit, common middleware bundled" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" diff --git a/modules/reitit-pedestal/project.clj b/modules/reitit-pedestal/project.clj index bd9c9a98..4a525f3f 100644 --- a/modules/reitit-pedestal/project.clj +++ b/modules/reitit-pedestal/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit-pedestal "0.3.10" +(defproject metosin/reitit-pedestal "0.4.2" :description "Reitit + Pedestal Integration" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" diff --git a/modules/reitit-ring/project.clj b/modules/reitit-ring/project.clj index b9c01b84..18d17717 100644 --- a/modules/reitit-ring/project.clj +++ b/modules/reitit-ring/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit-ring "0.3.10" +(defproject metosin/reitit-ring "0.4.2" :description "Reitit: Ring routing" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" diff --git a/modules/reitit-schema/project.clj b/modules/reitit-schema/project.clj index 15252e0e..540f6d04 100644 --- a/modules/reitit-schema/project.clj +++ b/modules/reitit-schema/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit-schema "0.3.10" +(defproject metosin/reitit-schema "0.4.2" :description "Reitit: Plumatic Schema coercion" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" diff --git a/modules/reitit-sieppari/project.clj b/modules/reitit-sieppari/project.clj index 4e63485d..c3f810e4 100644 --- a/modules/reitit-sieppari/project.clj +++ b/modules/reitit-sieppari/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit-sieppari "0.3.10" +(defproject metosin/reitit-sieppari "0.4.2" :description "Reitit: Sieppari Interceptors" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" diff --git a/modules/reitit-spec/project.clj b/modules/reitit-spec/project.clj index e6544e88..26b2cd4b 100644 --- a/modules/reitit-spec/project.clj +++ b/modules/reitit-spec/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit-spec "0.3.10" +(defproject metosin/reitit-spec "0.4.2" :description "Reitit: clojure.spec coercion" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" diff --git a/modules/reitit-swagger-ui/project.clj b/modules/reitit-swagger-ui/project.clj index 5cbe7d23..40687417 100644 --- a/modules/reitit-swagger-ui/project.clj +++ b/modules/reitit-swagger-ui/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit-swagger-ui "0.3.10" +(defproject metosin/reitit-swagger-ui "0.4.2" :description "Reitit: Swagger-ui support" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" diff --git a/modules/reitit-swagger/project.clj b/modules/reitit-swagger/project.clj index 73a66dce..d18c0082 100644 --- a/modules/reitit-swagger/project.clj +++ b/modules/reitit-swagger/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit-swagger "0.3.10" +(defproject metosin/reitit-swagger "0.4.2" :description "Reitit: Swagger-support" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" diff --git a/modules/reitit/project.clj b/modules/reitit/project.clj index 24a242de..bf168a0e 100644 --- a/modules/reitit/project.clj +++ b/modules/reitit/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit "0.3.10" +(defproject metosin/reitit "0.4.2" :description "Snappy data-driven router for Clojure(Script)" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" @@ -12,6 +12,7 @@ :dependencies [[metosin/reitit-core] [metosin/reitit-dev] [metosin/reitit-spec] + [metosin/reitit-malli] [metosin/reitit-schema] [metosin/reitit-ring] [metosin/reitit-middleware] @@ -20,4 +21,7 @@ [metosin/reitit-swagger] [metosin/reitit-swagger-ui] [metosin/reitit-frontend] - [metosin/reitit-sieppari]]) + [metosin/reitit-sieppari] + + ;; https://clojureverse.org/t/depending-on-the-right-versions-of-jackson-libraries/5111 + [com.fasterxml.jackson.core/jackson-core]]) diff --git a/perf-test/clj/reitit/opensensors_perf_test.clj b/perf-test/clj/reitit/opensensors_perf_test.clj index df5eff17..886f11e3 100644 --- a/perf-test/clj/reitit/opensensors_perf_test.clj +++ b/perf-test/clj/reitit/opensensors_perf_test.clj @@ -10,6 +10,8 @@ [compojure.core :refer [routes context ANY]] [calfpath.core :as cp] [calfpath.route :as cr] + [janus.route :as janus] + [janus.ring :as janus.ring] [io.pedestal.http.route.definition.table :as table] [io.pedestal.http.route.map-tree :as map-tree] @@ -309,6 +311,91 @@ (ANY "/topics/:topic" [] {:name :test/route47} handler) (ANY "/topics" [] {:name :test/route50} handler)))) +(def opensensors-janus-routes + (janus/router + ['root + {:v1 ["v1" handler + [[:public ["public" handler + [[:topics ["topics" handler {:test/route4 [true handler]}]] + [:users ["users" handler {:test/route16 [true handler]}]] + [:orgs ["orgs" handler {:test/route18 [true handler]}]]]]] + [:users ["users" handler + {:test/route36 [true handler + [[:orgs ["orgs" handler {:test/route5 [true handler]}]] + [:test/route7 ["invitations" handler]] + [:test/route9 ["topics" handler]] + [:bookmarks ["bookmarks" handler {:test/route10 ["followers" handler]}]] + [:test/route15 ["devices" handler + [[:test/route35 [true handler]] + [:client-id [true handler + {:test/route49 ["reset-password" handler]}]]]]] + [:test/route22 ["device-errors" handler]] + [:test/route24 ["usage-stats" handler]] + [:claim-device ["claim-device" handler {:test/route26 [true handler]}]] + [:test/route31 ["owned-orgs" handler]] + [:bookmark ["bookmark" handler {:test/route33 [true handler]}]] + [:test/route52 ["orgs" handler]] + [:test/route43 ["api-key" handler]] + [:test/route56 ["bookmarks" handler]]]]}]] + [:search ["search" handler + {:topics ["topics" handler {:test/route6 [true handler]}]}]] + [:test/route55 ["orgs" handler + [[:test/route42 [true handler + [[:test/route37 ["devices" handler + [[:test/route13 [true handler]]]]] + [:test/route12 ["usage-stats" handler]] + [:test/route19 ["invitations" handler]] + [:test/route38 ["members" handler + [[:test/route34 [true handler]]]]] + [:test/route17 ["errors" handler]] + [:confirm-membership ["confirm-membership" handler + {:test/route46 [true handler]}]] + [:test/route57 ["topics" handler]]]]]]]] + [:messages ["messages" handler + [[:user ["user" handler {:test/route14 [true handler]}]] + [:device ["device" handler {:test/route30 [true handler]}]] + [:topic ["topic" handler {:test/route48 [true handler]}]]]]] + [:test/route54 ["topics" handler + [[:test/route32 [true handler]]]]] + [:test/route41 ["whoami" handler]] + [:test/route51 ["login" handler]]]] + :v2 ["v2" handler + [[:test/route1 ["whoami" handler]] + [:users ["users" handler + {:test/route45 [true handler + [[:test/route2 ["datasets" handler]] + [:test/route25 ["devices" handler]] + [:test/route54 ["topics" handler + [[:test/route29 ["bulk" handler]]]]]]]}]] + [:public ["public" handler + [[:projects ["projects" handler + {:test/route27 [true handler + [[:test/route3 ["datasets" handler]]]]}]] + [:datasets ["datasets" handler + {:test/route28 [true handler]}]] + [:messages ["messages" handler + {:dataset ["dataset" handler + {:test/route53 [true handler]}]}]]]]] + [:datasets ["datasets" handler + {:test/route11 [true handler]}]] + [:test/route23 ["login" handler]] + [:orgs ["orgs" handler + {:org-id [true handler + {:test/route40 ["topics" handler]}]}]] + [:test/route44 ["schemas" handler]] + [:topics ["topics" handler + {:test/route47 [true handler]}]] + [:test/route50 ["topics" handler]]]]}])) + +(comment + (janus/identify opensensors-janus-routes "/v2/public/messages/dataset/987") + (-> opensensors-janus-routes + (janus/identify "/v2/public/messages/dataset/987") + (janus/dispatch* "/v2/public/messages/dataset/987")) + ((-> (janus.ring/make-dispatcher) + (janus.ring/wrap-identify opensensors-janus-routes)) + {:uri "/v2/public/messages/dataset/987"})) + (def opensensors-pedestal-routes (map-tree/router (table/table-routes @@ -562,6 +649,7 @@ ataraxy-f (partial ataraxy/matches opensensors-ataraxy-routes) compojure-f opensensors-compojure-routes pedestal-f (partial pedestal/find-route opensensors-pedestal-routes) + janus-f (-> (janus.ring/make-dispatcher) (janus.ring/wrap-identify opensensors-janus-routes)) b! (partial bench!! routes (fn [path] {:request-method :get, :uri path, :path-info path}) true)] ;; 2538ns @@ -621,7 +709,10 @@ (b! "bidi" bidi-f) ;; 19688ns - (b! "ataraxy" ataraxy-f))) + (b! "ataraxy" ataraxy-f) + + ;; 7550ns + (b! "janus" janus-f))) (comment (bench-rest!)) diff --git a/project.clj b/project.clj index 1dbc7aa2..04549292 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject metosin/reitit-parent "0.3.10" +(defproject metosin/reitit-parent "0.4.2" :description "Snappy data-driven router for Clojure(Script)" :url "https://github.com/metosin/reitit" :license {:name "Eclipse Public License" @@ -12,29 +12,32 @@ :url "https://github.com/metosin/reitit"} ;; TODO: need to verify that the code actually worked with Java1.8, see #242 :javac-options ["-Xlint:unchecked" "-target" "1.8" "-source" "1.8"] - :managed-dependencies [[metosin/reitit "0.3.10"] - [metosin/reitit-core "0.3.10"] - [metosin/reitit-dev "0.3.10"] - [metosin/reitit-spec "0.3.10"] - [metosin/reitit-malli "0.3.10"] - [metosin/reitit-schema "0.3.10"] - [metosin/reitit-ring "0.3.10"] - [metosin/reitit-middleware "0.3.10"] - [metosin/reitit-http "0.3.10"] - [metosin/reitit-interceptors "0.3.10"] - [metosin/reitit-swagger "0.3.10"] - [metosin/reitit-swagger-ui "0.3.10"] - [metosin/reitit-frontend "0.3.10"] - [metosin/reitit-sieppari "0.3.10"] - [metosin/reitit-pedestal "0.3.10"] + :managed-dependencies [[metosin/reitit "0.4.2"] + [metosin/reitit-core "0.4.2"] + [metosin/reitit-dev "0.4.2"] + [metosin/reitit-spec "0.4.2"] + [metosin/reitit-malli "0.4.2"] + [metosin/reitit-schema "0.4.2"] + [metosin/reitit-ring "0.4.2"] + [metosin/reitit-middleware "0.4.2"] + [metosin/reitit-http "0.4.2"] + [metosin/reitit-interceptors "0.4.2"] + [metosin/reitit-swagger "0.4.2"] + [metosin/reitit-swagger-ui "0.4.2"] + [metosin/reitit-frontend "0.4.2"] + [metosin/reitit-sieppari "0.4.2"] + [metosin/reitit-pedestal "0.4.2"] [metosin/ring-swagger-ui "3.24.3"] [metosin/spec-tools "0.10.0"] [metosin/schema-tools "0.12.1"] [metosin/muuntaja "0.6.6"] [metosin/jsonista "0.2.5"] - [metosin/sieppari "0.0.0-alpha7"] + [metosin/sieppari "0.0.0-alpha8"] [metosin/malli "0.0.1-20200108.194558-11"] + ;; https://clojureverse.org/t/depending-on-the-right-versions-of-jackson-libraries/5111 + [com.fasterxml.jackson.core/jackson-core "2.10.0"] + [meta-merge "1.0.0"] [fipp "0.6.22" :exclusions [org.clojure/core.rrb-vector]] [expound "0.8.4"] @@ -130,7 +133,8 @@ [aleph "0.4.6"] [ring/ring-defaults "0.3.2"] [ataraxy "0.4.2"] - [bidi "2.1.6"]]} + [bidi "2.1.6"] + [janus "1.3.0"]]} :analyze {:jvm-opts ^:replace ["-server" "-Dclojure.compiler.direct-linking=true" "-XX:+PrintCompilation"