diff --git a/CHANGELOG.md b/CHANGELOG.md index c09ab90d..135264e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -539,7 +539,7 @@ We use [Break Versioning][breakver]. The version numbers follow a `. request (ring/get-match) :data ::roles)] (if (and (seq required) (not (set/subset? required roles))) {:status 403, :body "forbidden"} diff --git a/doc/ring/reverse_routing.md b/doc/ring/reverse_routing.md index e2d7b5af..98d5dc0e 100644 --- a/doc/ring/reverse_routing.md +++ b/doc/ring/reverse_routing.md @@ -12,7 +12,7 @@ Below is an example how to do reverse routing from a ring handler: (ring/ring-handler (ring/router [["/users" - {:get (fn [{:keys [::r/router]}] + {:get (fn [{::r/keys [router]}] {:status 200 :body (for [i (range 10)] {:uri (-> router diff --git a/doc/ring/ring.md b/doc/ring/ring.md index ce51b122..5e1c1709 100644 --- a/doc/ring/ring.md +++ b/doc/ring/ring.md @@ -155,7 +155,7 @@ A middleware and a handler: (fn [request] (handler (update request ::acc (fnil conj []) id)))) -(defn handler [{:keys [::acc]}] +(defn handler [{::keys [acc]}] {:status 200, :body (conj acc :handler)}) ``` diff --git a/doc/ring/route_data_validation.md b/doc/ring/route_data_validation.md index a2f938b1..9609dc70 100644 --- a/doc/ring/route_data_validation.md +++ b/doc/ring/route_data_validation.md @@ -155,7 +155,7 @@ Let's reuse the `wrap-enforce-roles` from [Dynamic extensions](dynamic_extension (s/def ::roles (s/coll-of ::role :into #{})) (defn wrap-enforce-roles [handler] - (fn [{:keys [::roles] :as request}] + (fn [{::keys [roles] :as request}] (let [required (some-> request (ring/get-match) :data ::roles)] (if (and (seq required) (not (set/subset? required roles))) {:status 403, :body "forbidden"} diff --git a/doc/ring/transforming_middleware_chain.md b/doc/ring/transforming_middleware_chain.md index 20191c5b..ec75cd80 100644 --- a/doc/ring/transforming_middleware_chain.md +++ b/doc/ring/transforming_middleware_chain.md @@ -12,7 +12,7 @@ There is an extra option in ring-router (actually, in the underlying middleware- (fn [request] (handler (update request ::acc (fnil conj []) id)))) -(defn handler [{:keys [::acc]}] +(defn handler [{::keys [acc]}] {:status 200, :body (conj acc :handler)}) (def app diff --git a/examples/frontend-re-frame/src/cljs/frontend_re_frame/core.cljs b/examples/frontend-re-frame/src/cljs/frontend_re_frame/core.cljs index f7b33cc8..a15a34b0 100644 --- a/examples/frontend-re-frame/src/cljs/frontend_re_frame/core.cljs +++ b/examples/frontend-re-frame/src/cljs/frontend_re_frame/core.cljs @@ -18,7 +18,7 @@ (re-frame/reg-event-fx ::navigate - (fn [db [_ route]] + (fn [db [_ & route]] ;; See `navigate` effect in routes.cljs {::navigate! route})) @@ -59,8 +59,8 @@ ;; Triggering navigation from events. (re-frame/reg-fx ::navigate! - (fn [k params query] - (rfe/push-state k params query))) + (fn [route] + (apply rfe/push-state route))) ;;; Routes ;;; diff --git a/examples/http-swagger/project.clj b/examples/http-swagger/project.clj index 3c6b2194..776ee007 100644 --- a/examples/http-swagger/project.clj +++ b/examples/http-swagger/project.clj @@ -2,6 +2,6 @@ :description "Reitit Http App with Swagger" :dependencies [[org.clojure/clojure "1.10.0"] [ring/ring-jetty-adapter "1.7.1"] - [aleph "0.4.6"] + [aleph "0.4.7-alpha5"] [metosin/reitit "0.3.9"]] :repl-options {:init-ns example.server}) diff --git a/examples/http-swagger/src/example/server.clj b/examples/http-swagger/src/example/server.clj index bf2c5d55..4f4676af 100644 --- a/examples/http-swagger/src/example/server.clj +++ b/examples/http-swagger/src/example/server.clj @@ -15,7 +15,7 @@ [reitit.http.spec :as spec] [spec-tools.spell :as spell] [ring.adapter.jetty :as jetty] - [aleph.http :as client] + [aleph.http :as aleph] [muuntaja.core :as m] [clojure.java.io :as io] [clojure.spec.alpha :as s] @@ -71,7 +71,7 @@ :responses {200 {:body any?}} :handler (fn [{{{:keys [seed results]} :query} :parameters}] (d/chain - (client/get + (aleph/get "https://randomuser.me/api/" {:query-params {:seed seed, :results results}}) :body @@ -146,6 +146,7 @@ (defn start [] (jetty/run-jetty #'app {:port 3000, :join? false, :async true}) + ;(aleph/start-server (aleph/wrap-ring-async-handler #'app) {:port 3000}) (println "server running in port 3000")) (comment diff --git a/examples/ring-spec-swagger/project.clj b/examples/ring-spec-swagger/project.clj index 571781c5..8b90d687 100644 --- a/examples/ring-spec-swagger/project.clj +++ b/examples/ring-spec-swagger/project.clj @@ -4,4 +4,4 @@ [ring/ring-jetty-adapter "1.7.1"] [metosin/reitit "0.3.9"]] :repl-options {:init-ns example.server} - :profiles{:dev {:dependencies [[ring/ring-mock "0.3.2"]]}}) + :profiles {:dev {:dependencies [[ring/ring-mock "0.3.2"]]}}) diff --git a/modules/reitit-core/src/reitit/coercion.cljc b/modules/reitit-core/src/reitit/coercion.cljc index b9da1519..737847dc 100644 --- a/modules/reitit-core/src/reitit/coercion.cljc +++ b/modules/reitit-core/src/reitit/coercion.cljc @@ -70,7 +70,7 @@ (-> request :muuntaja/request :format)) ;; TODO: support faster key walking, walk/keywordize-keys is quite slow... -(defn request-coercer [coercion type model {:keys [::extract-request-format ::parameter-coercion] +(defn request-coercer [coercion type model {::keys [extract-request-format parameter-coercion] :or {extract-request-format extract-request-format-default parameter-coercion default-parameter-coercion}}] (if coercion diff --git a/modules/reitit-core/src/reitit/interceptor.cljc b/modules/reitit-core/src/reitit/interceptor.cljc index 5b3de7d7..b6bfade9 100644 --- a/modules/reitit-core/src/reitit/interceptor.cljc +++ b/modules/reitit-core/src/reitit/interceptor.cljc @@ -33,7 +33,7 @@ #?(:clj clojure.lang.Keyword :cljs cljs.core.Keyword) - (into-interceptor [this data {:keys [::registry] :as opts}] + (into-interceptor [this data {::keys [registry] :as opts}] (if-let [interceptor (if registry (registry this))] (into-interceptor interceptor data opts) (throw @@ -108,7 +108,7 @@ (chain interceptors nil nil)) ([interceptors data] (chain interceptors data nil)) - ([interceptors data {:keys [::transform] :or {transform identity} :as opts}] + ([interceptors data {::keys [transform] :or {transform identity} :as opts}] (let [transform (if (vector? transform) (apply comp (reverse transform)) transform)] (->> interceptors (keep #(into-interceptor % data opts)) @@ -119,7 +119,7 @@ (defn compile-result ([route opts] (compile-result route opts nil)) - ([[_ {:keys [interceptors handler] :as data}] {:keys [::queue] :as opts} _] + ([[_ {:keys [interceptors handler] :as data}] {::keys [queue] :as opts} _] (let [chain (chain (into (vec interceptors) [handler]) data opts)] (map->Endpoint {:interceptors chain diff --git a/modules/reitit-core/src/reitit/middleware.cljc b/modules/reitit-core/src/reitit/middleware.cljc index 51d206be..b27e1d0c 100644 --- a/modules/reitit-core/src/reitit/middleware.cljc +++ b/modules/reitit-core/src/reitit/middleware.cljc @@ -17,7 +17,7 @@ #?(:clj clojure.lang.Keyword :cljs cljs.core.Keyword) - (into-middleware [this data {:keys [::registry] :as opts}] + (into-middleware [this data {::keys [registry] :as opts}] (if-let [middleware (if registry (registry this))] (into-middleware middleware data opts) (throw @@ -83,7 +83,7 @@ (if scope {:scope scope}))))) (defn- expand-and-transform - [middleware data {:keys [::transform] :or {transform identity} :as opts}] + [middleware data {::keys [transform] :or {transform identity} :as opts}] (let [transform (if (vector? transform) (apply comp (reverse transform)) transform)] (->> middleware (keep #(into-middleware % data opts)) diff --git a/modules/reitit-core/src/reitit/spec.cljc b/modules/reitit-core/src/reitit/spec.cljc index c0317629..c00c717c 100644 --- a/modules/reitit-core/src/reitit/spec.cljc +++ b/modules/reitit-core/src/reitit/spec.cljc @@ -123,7 +123,7 @@ (->Problem p nil d spec problems))) (keep identity) (seq) (vec)))) -(defn validate [routes {:keys [spec ::wrap] :or {spec ::default-data, wrap identity}}] +(defn validate [routes {:keys [spec] ::keys [wrap] :or {spec ::default-data, wrap identity}}] (when-let [problems (validate-route-data routes wrap spec)] (exception/fail! ::invalid-route-data diff --git a/modules/reitit-frontend/src/reitit/frontend/history.cljs b/modules/reitit-frontend/src/reitit/frontend/history.cljs index 6950ee19..129d20b0 100644 --- a/modules/reitit-frontend/src/reitit/frontend/history.cljs +++ b/modules/reitit-frontend/src/reitit/frontend/history.cljs @@ -67,6 +67,29 @@ (first (.composedPath original-event)) (.-target event)))) +(defn ignore-anchor-click? + "Precicate to check if the anchor click event default action + should be ignored. This logic will ignore the event + if anchor href matches the route tree, and in this case + the page location is updated using History API." + [router e el uri] + (let [current-domain (if (exists? js/location) + (.getDomain (.parse Uri js/location)))] + (and (or (and (not (.hasScheme uri)) (not (.hasDomain uri))) + (= current-domain (.getDomain uri))) + (not (.-altKey e)) + (not (.-ctrlKey e)) + (not (.-metaKey e)) + (not (.-shiftKey e)) + (or (not (.hasAttribute el "target")) + (contains? #{"" "_self"} (.getAttribute el "target"))) + ;; Left button + (= 0 (.-button e)) + ;; isContentEditable property is inherited from parents, + ;; so if the anchor is inside contenteditable div, the property will be true. + (not (.-isContentEditable el)) + (reitit/match-by-path router (.getPath uri))))) + (defrecord Html5History [on-navigate router listen-key click-listen-key] History (-init [this] @@ -74,39 +97,24 @@ (fn [e] (-on-navigate this (-get-path this))) - current-domain - (if (exists? js/location) - (.getDomain (.parse Uri js/location))) + ignore-anchor-click-predicate (or (:ignore-anchor-click? this) + ignore-anchor-click?) ;; Prevent document load when clicking a elements, if the href points to URL that is part ;; of the routing tree." - ignore-anchor-click - (fn ignore-anchor-click - [e] - ;; Returns the next matching ancestor of event target - (when-let [el (closest-by-tag (event-target e) "a")] - (let [uri (.parse Uri (.-href el))] - (when (and (or (and (not (.hasScheme uri)) (not (.hasDomain uri))) - (= current-domain (.getDomain uri))) - (not (.-altKey e)) - (not (.-ctrlKey e)) - (not (.-metaKey e)) - (not (.-shiftKey e)) - (not (contains? #{"_blank" "self"} (.getAttribute el "target"))) - ;; Left button - (= 0 (.-button e)) - ;; isContentEditable property is inherited from parents, - ;; so if the anchor is inside contenteditable div, the property will be true. - (not (.-isContentEditable el)) - (reitit/match-by-path router (.getPath uri))) - (.preventDefault e) - (let [path (str (.getPath uri) - (when (.hasQuery uri) - (str "?" (.getQuery uri))) - (when (.hasFragment uri) - (str "#" (.getFragment uri))))] - (.pushState js/window.history nil "" path) - (-on-navigate this path))))))] + ignore-anchor-click (fn [e] + ;; Returns the next matching ancestor of event target + (when-let [el (closest-by-tag (event-target e) "a")] + (let [uri (.parse Uri (.-href el))] + (when (ignore-anchor-click-predicate router e el uri) + (.preventDefault e) + (let [path (str (.getPath uri) + (when (.hasQuery uri) + (str "?" (.getQuery uri))) + (when (.hasFragment uri) + (str "#" (.getFragment uri))))] + (.pushState js/window.history nil "" path) + (-on-navigate this path))))))] (-on-navigate this (-get-path this)) (assoc this :listen-key (gevents/listen js/window goog.events.EventType.POPSTATE handler false) @@ -135,15 +143,24 @@ - on-navigate Function to be called when route changes. Takes two parameters, ´match´ and ´history´ object. Options: - - :use-fragment (default true) If true, onhashchange and location hash are used to store current route." + - :use-fragment (default true) If true, onhashchange and location hash are used to store current route. + + Options (Html5History): + - :ignore-anchor-click? Function (router, event, anchor element, uri) which will be called to + check if the anchor click event should be ignored. + To extend built-in check, you can call `reitit.frontend.history/ignore-anchor-click?` + function, which will ignore clicks if the href matches route tree." ([router on-navigate] (start! router on-navigate nil)) ([router on-navigate {:keys [use-fragment] - :or {use-fragment true}}] - (let [opts {:router router - :on-navigate on-navigate}] + :or {use-fragment true} + :as opts}] + (let [opts (-> opts + (dissoc :use-fragment) + (assoc :router router + :on-navigate on-navigate))] (-init (if use-fragment (map->FragmentHistory opts) (map->Html5History opts)))))) diff --git a/modules/reitit-http/src/reitit/http.cljc b/modules/reitit-http/src/reitit/http.cljc index ef62ad08..afd39a80 100644 --- a/modules/reitit-http/src/reitit/http.cljc +++ b/modules/reitit-http/src/reitit/http.cljc @@ -13,7 +13,7 @@ (update acc method expand opts) acc)) data ring/http-methods)]) -(defn compile-result [[path data] {:keys [::default-options-handler] :as opts}] +(defn compile-result [[path data] {::keys [default-options-handler] :as opts}] (let [[top childs] (ring/group-keys data) childs (cond-> childs (and (not (:options childs)) (not (:handler top)) default-options-handler) @@ -127,7 +127,7 @@ (dissoc :data) ; data is already merged into routes (cond-> (seq interceptors) (update-in [:data :interceptors] (partial into (vec interceptors))))) - router (reitit.http/router (r/routes router) router-opts) + router (reitit.http/router (r/routes router) router-opts) ;; will re-compile the interceptors enrich-request (ring/create-enrich-request inject-match? inject-router?) enrich-default-request (ring/create-enrich-default-request inject-router?)] (with-meta diff --git a/modules/reitit-interceptors/src/reitit/http/interceptors/dev.clj b/modules/reitit-interceptors/src/reitit/http/interceptors/dev.clj index bd652885..285434f4 100644 --- a/modules/reitit-interceptors/src/reitit/http/interceptors/dev.clj +++ b/modules/reitit-interceptors/src/reitit/http/interceptors/dev.clj @@ -24,7 +24,7 @@ (update :request dissoc ::r/match ::r/router))) (defn- handle [name stage] - (fn [{:keys [::original ::previous] :as ctx}] + (fn [{::keys [previous] :as ctx}] (let [current (polish ctx) previous (polish previous)] (printer/print-doc (diff-doc stage name previous current) printer) diff --git a/modules/reitit-middleware/src/reitit/ring/middleware/dev.clj b/modules/reitit-middleware/src/reitit/ring/middleware/dev.clj index 2d74c63d..de89996e 100644 --- a/modules/reitit-middleware/src/reitit/ring/middleware/dev.clj +++ b/modules/reitit-middleware/src/reitit/ring/middleware/dev.clj @@ -18,13 +18,13 @@ (defn polish [request] (dissoc request ::r/match ::r/router ::original ::previous)) -(defn printed-request [name {:keys [::original ::previous] :as request}] +(defn printed-request [name {::keys [previous] :as request}] (printer/print-doc (diff-doc :request name (polish previous) (polish request)) printer) (-> request (update ::original (fnil identity request)) (assoc ::previous request))) -(defn printed-response [name {:keys [::original ::previous] :as response}] +(defn printed-response [name {::keys [previous] :as response}] (printer/print-doc (diff-doc :response name (polish previous) (polish response)) printer) (-> response (update ::original (fnil identity response)) diff --git a/modules/reitit-pedestal/src/reitit/pedestal.clj b/modules/reitit-pedestal/src/reitit/pedestal.clj index 115ac991..fcca5a46 100644 --- a/modules/reitit-pedestal/src/reitit/pedestal.clj +++ b/modules/reitit-pedestal/src/reitit/pedestal.clj @@ -49,7 +49,7 @@ Executor (queue [_ interceptors] (->> interceptors - (map (fn [{:keys [::interceptor/handler] :as interceptor}] + (map (fn [{::interceptor/keys [handler] :as interceptor}] (or handler interceptor))) (keep ->interceptor))) (enqueue [_ context interceptors] diff --git a/modules/reitit-ring/src/reitit/ring.cljc b/modules/reitit-ring/src/reitit/ring.cljc index f0d769f4..81c72b94 100644 --- a/modules/reitit-ring/src/reitit/ring.cljc +++ b/modules/reitit-ring/src/reitit/ring.cljc @@ -28,7 +28,7 @@ (update acc method expand opts) acc)) data http-methods)]) -(defn compile-result [[path data] {:keys [::default-options-handler] :as opts}] +(defn compile-result [[path data] {::keys [default-options-handler] :as opts}] (let [[top childs] (group-keys data) childs (cond-> childs (and (not (:options childs)) (not (:handler top)) default-options-handler) diff --git a/modules/reitit-sieppari/src/reitit/interceptor/sieppari.clj b/modules/reitit-sieppari/src/reitit/interceptor/sieppari.clj index e7d0faed..1198dff4 100644 --- a/modules/reitit-sieppari/src/reitit/interceptor/sieppari.clj +++ b/modules/reitit-sieppari/src/reitit/interceptor/sieppari.clj @@ -9,7 +9,7 @@ (queue [_ interceptors] (queue/into-queue (map - (fn [{:keys [::interceptor/handler] :as interceptor}] + (fn [{::interceptor/keys [handler] :as interceptor}] (or handler interceptor)) interceptors))) (execute [_ interceptors request] diff --git a/modules/reitit-swagger/src/reitit/swagger.cljc b/modules/reitit-swagger/src/reitit/swagger.cljc index 567c5ab6..1d4491ad 100644 --- a/modules/reitit-swagger/src/reitit/swagger.cljc +++ b/modules/reitit-swagger/src/reitit/swagger.cljc @@ -71,7 +71,7 @@ "Create a ring handler to emit swagger spec. Collects all routes from router which have an intersecting `[:swagger :id]` and which are not marked with `:no-doc` route data." (fn create-swagger - ([{:keys [::r/router ::r/match :request-method]}] + ([{::r/keys [router match] :keys [request-method]}] (let [{:keys [id] :or {id ::default} :as swagger} (-> match :result request-method :data :swagger) ids (trie/into-set id) strip-top-level-keys #(dissoc % :id :info :host :basePath :definitions :securityDefinitions) diff --git a/test/clj/reitit/http_test.clj b/test/clj/reitit/http_test.clj index 934ef9bc..4235b9ce 100644 --- a/test/clj/reitit/http_test.clj +++ b/test/clj/reitit/http_test.clj @@ -11,7 +11,7 @@ (defn interceptor [name] {:enter (fn [ctx] (update-in ctx [:request ::i] (fnil conj []) name))}) -(defn handler [{:keys [::i]}] +(defn handler [{::keys [i]}] {:status 200 :body (conj i :ok)}) (deftest http-router-test @@ -89,7 +89,7 @@ (is (= name (-> (r/match-by-name router name) :data :name)))))))) (def enforce-roles-interceptor - {:enter (fn [{{:keys [::roles] :as request} :request :as ctx}] + {:enter (fn [{{::keys [roles] :as request} :request :as ctx}] (let [required (some-> request (http/get-match) :data ::roles)] (if (and (seq required) (not (set/intersection required roles))) (-> ctx @@ -280,7 +280,7 @@ (let [interceptor (fn [name] {:name name :enter (fn [ctx] (update-in ctx [:request ::i] (fnil conj []) name))}) - handler (fn [{:keys [::i]}] {:status 200 :body (conj i :ok)}) + handler (fn [{::keys [i]}] {:status 200 :body (conj i :ok)}) request {:uri "/api/avaruus" :request-method :get} create (fn [options] (http/ring-handler @@ -492,14 +492,14 @@ (testing "1-arity" ((http/ring-handler (http/router []) - (fn [{:keys [::r/router]}] + (fn [{::r/keys [router]}] (is router)) {:executor sieppari/executor}) {})) (testing "3-arity" ((http/ring-handler (http/router []) - (fn [{:keys [::r/router]}] + (fn [{::r/keys [router]}] (is router)) {:executor sieppari/executor}) {} ::respond ::raise))) diff --git a/test/cljc/reitit/ring_test.cljc b/test/cljc/reitit/ring_test.cljc index 5dead344..7c1d3432 100644 --- a/test/cljc/reitit/ring_test.cljc +++ b/test/cljc/reitit/ring_test.cljc @@ -19,7 +19,7 @@ (mw handler (keyword (str name "_" name2 "_" name3)))) (defn handler - ([{:keys [::mw]}] + ([{::keys [mw]}] {:status 200 :body (conj mw :ok)}) ([request respond _] (respond (handler request)))) @@ -119,7 +119,7 @@ (is (= name (-> (r/match-by-name router name) :data :name)))))))) (defn wrap-enforce-roles [handler] - (fn [{:keys [::roles] :as request}] + (fn [{::keys [roles] :as request}] (let [required (some-> request (ring/get-match) :data ::roles)] (if (and (seq required) (not (set/intersection required roles))) {:status 403, :body "forbidden"} @@ -399,7 +399,7 @@ :wrap (fn [handler] (fn [request] (handler (update request ::mw (fnil conj []) name))))}) - handler (fn [{:keys [::mw]}] {:status 200 :body (conj mw :ok)}) + handler (fn [{::keys [mw]}] {:status 200 :body (conj mw :ok)}) request {:uri "/api/avaruus" :request-method :get} create (fn [options] (ring/ring-handler @@ -583,13 +583,13 @@ (testing "1-arity" ((ring/ring-handler (ring/router []) - (fn [{:keys [::r/router]}] + (fn [{::r/keys [router]}] (is router))) {})) (testing "3-arity" ((ring/ring-handler (ring/router []) - (fn [{:keys [::r/router]} _ _] + (fn [{::r/keys [router]} _ _] (is router))) {} ::respond ::raise)))