diff --git a/src/compojure/core.clj b/src/compojure/core.clj index 32b25de9..304cfb86 100644 --- a/src/compojure/core.clj +++ b/src/compojure/core.clj @@ -134,9 +134,17 @@ (defn- wrap-route-info [handler route-info] (fn ([request] - (handler (assoc request :compojure/route route-info))) + (let [full-route (str (:compojure/context-path request) (second route-info))] + (handler (assoc request + :compojure/route route-info + :compojure/full-route full-route)))) ([request respond raise] - (handler (assoc request :compojure/route route-info) respond raise)))) + (let [full-route (str (:compojure/context-path request) (second route-info))] + (handler (assoc request + :compojure/route route-info + :compojure/full-route full-route) + respond + raise))))) (defn- wrap-route-matches [handler method path] (fn @@ -251,35 +259,34 @@ (defn- remove-suffix [path suffix] (subs path 0 (- (count path) (count suffix)))) -(defn- context-request [request route] +(defn- context-request [request route context-path] (if-let [params (clout/route-matches route request)] (let [uri (:uri request) - path (:path-info request uri) - context (or (:context request) "") subpath (:__path-info params) params (dissoc params :__path-info)] (-> 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/context-path (fn [ctx] (str ctx context-path))))))) (defn- context-route [route] (let [re-context {:__path-info #"|/.*"}] (cond (string? route) - (clout/route-compile (str route ":__path-info") re-context) + (clout/route-compile (str route ":__path-info") re-context) (and (vector? route) (literal? route)) - (clout/route-compile - (str (first route) ":__path-info") - (merge (apply hash-map (rest route)) re-context)) + (clout/route-compile + (str (first route) ":__path-info") + (merge (apply hash-map (rest route)) re-context)) (vector? route) - `(clout/route-compile - (str ~(first route) ":__path-info") - ~(merge (apply hash-map (rest route)) re-context)) + `(clout/route-compile + (str ~(first route) ":__path-info") + ~(merge (apply hash-map (rest route)) re-context)) :else - `(clout/route-compile (str ~route ":__path-info") ~re-context)))) + `(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 +299,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 +318,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..cf35e703 100644 --- a/test/compojure/core_test.clj +++ b/test/compojure/core_test.clj @@ -38,7 +38,7 @@ (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))) @@ -212,7 +212,7 @@ (let [handler (GET "/ip/:ip" [ip] ip) cxt-handler (context "/ip/:ip" [ip] (GET "/" [] ip)) in-cxt-handler (context "/ip" [] (GET "/:ip" [ip] ip)) - request (mock/request :get "/ip/0%3A0%3A0%3A0%3A0%3A0%3A0%3A1%250") ] + request (mock/request :get "/ip/0%3A0%3A0%3A0%3A0%3A0%3A0%3A1%250")] (is (= (-> request handler :body) "0:0:0:0:0:0:0:1%0")) (is (= (-> request cxt-handler :body) "0:0:0:0:0:0:0:1%0")) (is (= (-> request in-cxt-handler :body) "0:0:0:0:0:0:0:1%0")))) @@ -221,7 +221,7 @@ (let [handler (GET "/emote/:emote" [emote] emote) cxt-handler (context "/emote/:emote" [emote] (GET "/" [] emote)) in-cxt-handler (context "/emote" [] (GET "/:emote" [emote] emote)) - request (mock/request :get "/emote/%5C%3F%2F") ] + request (mock/request :get "/emote/%5C%3F%2F")] (is (= (-> request handler :body) "\\?/")) (is (= (-> request cxt-handler :body) "\\?/")) (is (= (-> request in-cxt-handler :body) "\\?/")))) @@ -323,7 +323,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/context-path) + "/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/context-path) + "/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"