From 5abd2eb57092fc9d4ec7682dd278b1d9382bba88 Mon Sep 17 00:00:00 2001 From: Liam Chen Date: Thu, 28 Apr 2022 12:09:12 -0400 Subject: [PATCH] Add a full-route key to the request map This provides access to the full route that contains the common prefix. The full-route info is added to the :compojure/full-route key in the request map. We use :compojure/route to get the route info and add it to the attributes of our metrics and traces, but when compojure.core/context is used, we are not able to get the parameters that are not instantiated. This change adds :compojure/full-route key that serves similarly as the existing :compojure/route does - the only difference is that the new key has a common prefix. Co-authored-by: Liam Chen Co-authored-by: Claire Alvis --- src/compojure/core.clj | 31 +++++++++++++++++++++---------- test/compojure/core_test.clj | 30 ++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/compojure/core.clj b/src/compojure/core.clj index 32b25de9..daccff02 100644 --- a/src/compojure/core.clj +++ b/src/compojure/core.clj @@ -132,11 +132,20 @@ (handler request respond raise))))) (defn- wrap-route-info [handler route-info] - (fn - ([request] - (handler (assoc request :compojure/route route-info))) - ([request respond raise] - (handler (assoc request :compojure/route route-info) respond raise)))) + (let [[_ path] route-info] + (fn + ([request] + (let [full-route (str (:compojure/route-context request) path)] + (handler (assoc request + :compojure/route route-info + :compojure/full-route full-route)))) + ([request respond raise] + (let [full-route (str (:compojure/route-context request) path)] + (handler (assoc request + :compojure/route route-info + :compojure/full-route full-route) + respond + raise)))))) (defn- wrap-route-matches [handler method path] (fn @@ -251,7 +260,7 @@ (defn- remove-suffix [path suffix] (subs path 0 (- (count path) (count suffix)))) -(defn- context-request [request route] +(defn- context-request [request route route-context] (if-let [params (clout/route-matches route request)] (let [uri (:uri request) path (:path-info request uri) @@ -261,7 +270,8 @@ (-> request (assoc-route-params (decode-route-params params)) (assoc :path-info (if (= subpath "") "/" subpath) - :context (remove-suffix uri subpath)))))) + :context (remove-suffix uri subpath)) + (update :compojure/route-context str route-context))))) (defn- context-route [route] (let [re-context {:__path-info #"|/.*"}] @@ -279,7 +289,7 @@ :else `(clout/route-compile (str ~route ":__path-info") ~re-context)))) -(defn ^:no-doc make-context [route make-handler] +(defn ^:no-doc make-context [route path make-handler] (letfn [(handler ([request] (when-let [context-handler (make-handler request)] @@ -292,10 +302,10 @@ handler (fn ([request] - (if-let [request (context-request request route)] + (if-let [request (context-request request route path)] (handler request))) ([request respond raise] - (if-let [request (context-request request route)] + (if-let [request (context-request request route path)] (handler request respond raise) (respond nil))))))) @@ -311,6 +321,7 @@ [path args & routes] `(make-context ~(context-route path) + ~path (fn [request#] (let-request [~args request#] (routes ~@routes))))) diff --git a/test/compojure/core_test.clj b/test/compojure/core_test.clj index f5430801..95ea8756 100644 --- a/test/compojure/core_test.clj +++ b/test/compojure/core_test.clj @@ -38,7 +38,11 @@ (assoc :params {:y "bar"}))] ((GET "/:x" [x :as r] (is (= x "foo")) - (is (= (dissoc r :params :route-params :compojure/route) + (is (= (dissoc r + :params + :route-params + :compojure/route + :compojure/full-route) (dissoc req :params))) nil) req))) @@ -323,7 +327,29 @@ request (route (mock/request :post "/foo/1" {}))] (testing "ANY request has matched route information" (is (= (request :compojure/route) - [:any "/foo/:id"]))))) + [:any "/foo/:id"])) + (is (= (request :compojure/full-route) + "/foo/:id")))) + + (let [route (context "/foo/:foo-id" [_] (GET "/bar/:bar-id" req req)) + request (route (mock/request :get "/foo/1/bar/2"))] + (testing "request has matched route information with path prefix" + (is (= (request :compojure/route) + [:get "/bar/:bar-id"])) + (is (= (request :compojure/route-context) + "/foo/:foo-id")) + (is (= (request :compojure/full-route) + "/foo/:foo-id/bar/:bar-id")))) + + (let [route (context "/foo/:foo-id" [_] + (context "/bar/:bar-id" [_] + (GET "/baz/:baz-id" req req))) + request (route (mock/request :get "/foo/1/bar/2/baz/3"))] + (testing "request has matched route information with multiple path prefix" + (is (= (request :compojure/route-context) + "/foo/:foo-id/bar/:bar-id")) + (is (= (request :compojure/full-route) + "/foo/:foo-id/bar/:bar-id/baz/:baz-id"))))) (deftest route-async-test (testing "single route"