From c3a3b923a78167e9301af5817eaef387850cc8f0 Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Fri, 31 Aug 2018 10:01:01 +0300 Subject: [PATCH 1/5] wip --- examples/pedestal/.gitignore | 11 +++++++ examples/pedestal/README.md | 17 +++++++++++ examples/pedestal/project.clj | 7 +++++ examples/pedestal/src/example/pedestal.clj | 35 ++++++++++++++++++++++ examples/pedestal/src/example/server.clj | 34 +++++++++++++++++++++ 5 files changed, 104 insertions(+) create mode 100644 examples/pedestal/.gitignore create mode 100644 examples/pedestal/README.md create mode 100644 examples/pedestal/project.clj create mode 100644 examples/pedestal/src/example/pedestal.clj create mode 100644 examples/pedestal/src/example/server.clj diff --git a/examples/pedestal/.gitignore b/examples/pedestal/.gitignore new file mode 100644 index 00000000..c53038ec --- /dev/null +++ b/examples/pedestal/.gitignore @@ -0,0 +1,11 @@ +/target +/classes +/checkouts +pom.xml +pom.xml.asc +*.jar +*.class +/.lein-* +/.nrepl-port +.hgignore +.hg/ diff --git a/examples/pedestal/README.md b/examples/pedestal/README.md new file mode 100644 index 00000000..281db0cd --- /dev/null +++ b/examples/pedestal/README.md @@ -0,0 +1,17 @@ +# reitit-http example with pedestal + +## Usage + +```clj +> lein repl +(start) +``` + +Go with browser to: + +* http://localhost:3000/api/sync - synchronous +* http://localhost:3000/api/async - with core.async + +## License + +Copyright © 2018 Metosin Oy diff --git a/examples/pedestal/project.clj b/examples/pedestal/project.clj new file mode 100644 index 00000000..e040f9ff --- /dev/null +++ b/examples/pedestal/project.clj @@ -0,0 +1,7 @@ +(defproject ring-example "0.1.0-SNAPSHOT" + :description "Reitit-http with pedestal" + :dependencies [[org.clojure/clojure "1.9.0"] + [io.pedestal/pedestal.service "0.5.1"] + [io.pedestal/pedestal.jetty "0.5.1"] + [metosin/reitit "0.2.0-SNAPSHOT"]] + :repl-options {:init-ns example.server}) diff --git a/examples/pedestal/src/example/pedestal.clj b/examples/pedestal/src/example/pedestal.clj new file mode 100644 index 00000000..dae10efc --- /dev/null +++ b/examples/pedestal/src/example/pedestal.clj @@ -0,0 +1,35 @@ +(ns example.pedestal + (:require [io.pedestal.interceptor.chain :as chain] + [io.pedestal.interceptor :as interceptor] + [reitit.http :as http]) + (:import (reitit.interceptor Executor))) + +(def pedestal-executor + (reify + Executor + (queue [_ interceptors] + (->> interceptors + (map (fn [{:keys [::interceptor/handler] :as interceptor}] + (or handler interceptor))) + (map interceptor/interceptor))) + (enqueue [_ context interceptors] + (chain/enqueue context interceptors)))) + +(defn routing-interceptor + ([router] + (routing-interceptor router nil)) + ([router default-handler] + (routing-interceptor router default-handler nil)) + ([router default-handler opts] + (interceptor/interceptor + (http/routing-interceptor + router + default-handler + (merge {:executor pedestal-executor} opts))))) + +(def router http/router) + +(defn with-reitit-router [spec router] + (-> spec + (update ::http/interceptors (comp vec butlast)) + (update ::http/interceptors conj router))) diff --git a/examples/pedestal/src/example/server.clj b/examples/pedestal/src/example/server.clj new file mode 100644 index 00000000..f46bc186 --- /dev/null +++ b/examples/pedestal/src/example/server.clj @@ -0,0 +1,34 @@ +(ns example.server + (:require [io.pedestal.http :as http] + [io.pedestal.http.route :as route] + [io.pedestal.http.body-params :as body-params] + [io.pedestal.http.route.definition :refer [defroutes]])) + +(defn hello-world [request] + (let [name (get-in request [:params :name] "World")] + {:status 200 :body (str "Hello " name "!\n")})) + +(defroutes routes + [[["/" + ["/hello" {:get hello-world}]]]]) + +(def service {:env :prod + ::http/routes routes + ::http/resource-path "/public" + ::http/type :jetty + ::http/port 8080}) + +(defn start [] + (-> service/service + (merge {:env :dev + ::http/join? false + ::http/routes #(deref #'routes) + ::http/allowed-origins {:creds true :allowed-origins (constantly true)}}) + http/default-interceptors + http/dev-interceptors + http/create-server + http/start)) + + +(comment + (start)) From a23cd116b77e88df4b6163623ee07def5b45a59a Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Fri, 31 Aug 2018 10:01:15 +0300 Subject: [PATCH 2/5] deps --- examples/pedestal/project.clj | 4 ++-- project.clj | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/pedestal/project.clj b/examples/pedestal/project.clj index e040f9ff..42d045f8 100644 --- a/examples/pedestal/project.clj +++ b/examples/pedestal/project.clj @@ -1,7 +1,7 @@ (defproject ring-example "0.1.0-SNAPSHOT" :description "Reitit-http with pedestal" :dependencies [[org.clojure/clojure "1.9.0"] - [io.pedestal/pedestal.service "0.5.1"] - [io.pedestal/pedestal.jetty "0.5.1"] + [io.pedestal/pedestal.service "0.5.4"] + [io.pedestal/pedestal.jetty "0.5.4"] [metosin/reitit "0.2.0-SNAPSHOT"]] :repl-options {:init-ns example.server}) diff --git a/project.clj b/project.clj index f09c32d6..9b1e5c84 100644 --- a/project.clj +++ b/project.clj @@ -81,7 +81,8 @@ :dependencies [[compojure "1.6.1"] [ring/ring-defaults "0.3.2"] [ikitommi/immutant-web "3.0.0-alpha1"] - [io.pedestal/pedestal.route "0.5.4"] + [io.pedestal/pedestal.service "0.5.4"] + [io.pedestal/pedestal.jetty "0.5.4"] [org.clojure/core.async "0.4.474"] [metosin/sieppari "0.0.0-alpha4"] [yada "1.2.13"] From 07acbb275fb706cd17f0ad636988eaff1158ad07 Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Fri, 31 Aug 2018 10:45:51 +0300 Subject: [PATCH 3/5] Pedestal-sample --- examples/pedestal/src/example/server.clj | 58 ++++++++++++------- .../src/{example => reitit}/pedestal.clj | 19 +++--- .../reitit-core/src/reitit/interceptor.cljc | 5 +- modules/reitit-http/src/reitit/http.cljc | 27 +++++++++ 4 files changed, 79 insertions(+), 30 deletions(-) rename examples/pedestal/src/{example => reitit}/pedestal.clj (67%) diff --git a/examples/pedestal/src/example/server.clj b/examples/pedestal/src/example/server.clj index f46bc186..c665e2ba 100644 --- a/examples/pedestal/src/example/server.clj +++ b/examples/pedestal/src/example/server.clj @@ -1,34 +1,50 @@ (ns example.server (:require [io.pedestal.http :as http] - [io.pedestal.http.route :as route] - [io.pedestal.http.body-params :as body-params] - [io.pedestal.http.route.definition :refer [defroutes]])) + [reitit.pedestal :as pedestal] + [reitit.http :as reitit-http] + [reitit.ring :as ring])) -(defn hello-world [request] - (let [name (get-in request [:params :name] "World")] - {:status 200 :body (str "Hello " name "!\n")})) +(defn interceptor [x] + {:enter (fn [ctx] (println ">>" x) ctx) + :leave (fn [ctx] (println "<<" x) ctx)}) -(defroutes routes - [[["/" - ["/hello" {:get hello-world}]]]]) +(def routing-interceptor + (pedestal/routing-interceptor + (reitit-http/router + ["/api" + {:interceptors [[interceptor :api] + [interceptor :apa]]} -(def service {:env :prod - ::http/routes routes - ::http/resource-path "/public" - ::http/type :jetty - ::http/port 8080}) + ["/ping" + {:interceptors [[interceptor :ping]] + :get {:interceptors [[interceptor :get]] + :handler (fn [_] + (println "handler") + {:status 200, + :body "pong"})}}]] + {:data {:interceptors [[interceptor :router]]}}) + (ring/create-default-handler) + {:interceptors [[interceptor :top]]})) + +(defonce server (atom nil)) (defn start [] - (-> service/service + (when @server + (http/stop @server) + (println "server stopped")) + (-> {:env :prod + ::http/routes [] + ::http/resource-path "/public" + ::http/type :jetty + ::http/port 3000} (merge {:env :dev ::http/join? false - ::http/routes #(deref #'routes) ::http/allowed-origins {:creds true :allowed-origins (constantly true)}}) - http/default-interceptors + (pedestal/default-interceptors routing-interceptor) http/dev-interceptors http/create-server - http/start)) + http/start + (->> (reset! server))) + (println "server running in port 3000")) - -(comment - (start)) +(start) diff --git a/examples/pedestal/src/example/pedestal.clj b/examples/pedestal/src/reitit/pedestal.clj similarity index 67% rename from examples/pedestal/src/example/pedestal.clj rename to examples/pedestal/src/reitit/pedestal.clj index dae10efc..7d8de821 100644 --- a/examples/pedestal/src/example/pedestal.clj +++ b/examples/pedestal/src/reitit/pedestal.clj @@ -1,7 +1,9 @@ -(ns example.pedestal +(ns reitit.pedestal (:require [io.pedestal.interceptor.chain :as chain] [io.pedestal.interceptor :as interceptor] - [reitit.http :as http]) + [io.pedestal.http :as http] + [reitit.interceptor] + [reitit.http]) (:import (reitit.interceptor Executor))) (def pedestal-executor @@ -20,16 +22,17 @@ (routing-interceptor router nil)) ([router default-handler] (routing-interceptor router default-handler nil)) - ([router default-handler opts] + ([router default-handler {:keys [interceptors]}] (interceptor/interceptor - (http/routing-interceptor + (reitit.http/routing-interceptor router default-handler - (merge {:executor pedestal-executor} opts))))) + {:executor pedestal-executor + :interceptors interceptors})))) -(def router http/router) - -(defn with-reitit-router [spec router] +(defn default-interceptors [spec router] (-> spec + (assoc ::http/routes []) + (http/default-interceptors) (update ::http/interceptors (comp vec butlast)) (update ::http/interceptors conj router))) diff --git a/modules/reitit-core/src/reitit/interceptor.cljc b/modules/reitit-core/src/reitit/interceptor.cljc index a5139c0a..c2d7e674 100644 --- a/modules/reitit-core/src/reitit/interceptor.cljc +++ b/modules/reitit-core/src/reitit/interceptor.cljc @@ -18,7 +18,10 @@ (execute [this interceptors request] [this interceptors request respond raise] - "executes the interceptor chain")) + "executes the interceptor chain with a request") + (enqueue + [this context interceptors] + "enqueues the interceptors into the queue")) (defn context [request] (map->Context {:request request})) diff --git a/modules/reitit-http/src/reitit/http.cljc b/modules/reitit-http/src/reitit/http.cljc index 373df4db..1befcff7 100644 --- a/modules/reitit-http/src/reitit/http.cljc +++ b/modules/reitit-http/src/reitit/http.cljc @@ -61,6 +61,33 @@ (let [opts (meta-merge {:coerce coerce-handler, :compile compile-result} opts)] (r/router data opts)))) +(defn routing-interceptor + "A Pedestal-style routing interceptor that enqueus the interceptors into context." + [router default-handler {:keys [interceptors executor]}] + (let [default-handler (or default-handler (fn ([_]))) + default-interceptors (->> interceptors + (map #(interceptor/into-interceptor % nil (r/options router)))) + default-queue (interceptor/queue executor default-interceptors)] + {:name ::router + :enter (fn [{:keys [request] :as context}] + (if-let [match (r/match-by-path router (:uri request))] + (let [method (:request-method request) + path-params (:path-params match) + endpoint (-> match :result method) + interceptors (or (:queue endpoint) (:interceptors endpoint)) + request (-> request + (impl/fast-assoc :path-params path-params) + (impl/fast-assoc ::r/match match) + (impl/fast-assoc ::r/router router)) + context (assoc context :request request) + queue (interceptor/queue executor (concat default-interceptors interceptors))] + (interceptor/enqueue executor context queue)) + (interceptor/enqueue executor context default-queue))) + :leave (fn [context] + (if-not (:response context) + (assoc context :response (default-handler (:request context))) + context))})) + (defn ring-handler "Creates a ring-handler out of a http-router, a default ring-handler and options map, with the following keys: From 9ca63b545b0269770c4e09f59cafbba1dace71fd Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Fri, 31 Aug 2018 10:56:56 +0300 Subject: [PATCH 4/5] wip --- examples/pedestal/src/example/server.clj | 45 +++++++++++++++--------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/examples/pedestal/src/example/server.clj b/examples/pedestal/src/example/server.clj index c665e2ba..05e55749 100644 --- a/examples/pedestal/src/example/server.clj +++ b/examples/pedestal/src/example/server.clj @@ -1,7 +1,8 @@ (ns example.server - (:require [io.pedestal.http :as http] + (:require [io.pedestal.http] + [clojure.core.async :as a] [reitit.pedestal :as pedestal] - [reitit.http :as reitit-http] + [reitit.http :as http] [reitit.ring :as ring])) (defn interceptor [x] @@ -10,18 +11,27 @@ (def routing-interceptor (pedestal/routing-interceptor - (reitit-http/router + (http/router ["/api" {:interceptors [[interceptor :api] [interceptor :apa]]} - ["/ping" - {:interceptors [[interceptor :ping]] + ["/sync" + {:interceptors [[interceptor :sync]] :get {:interceptors [[interceptor :get]] :handler (fn [_] (println "handler") {:status 200, - :body "pong"})}}]] + :body "pong"})}}] + + ["/async" + {:interceptors [[interceptor :async]] + :get {:interceptors [[interceptor :get]] + :handler (fn [_] + (a/go + (println "handler") + {:status 200, + :body "pong"}))}}]] {:data {:interceptors [[interceptor :router]]}}) (ring/create-default-handler) {:interceptors [[interceptor :top]]})) @@ -30,21 +40,22 @@ (defn start [] (when @server - (http/stop @server) + (io.pedestal.http/stop @server) (println "server stopped")) (-> {:env :prod - ::http/routes [] - ::http/resource-path "/public" - ::http/type :jetty - ::http/port 3000} + :io.pedestal.http/routes [] + :io.pedestal.http/resource-path "/public" + :io.pedestal.http/type :jetty + :io.pedestal.http/port 3000} (merge {:env :dev - ::http/join? false - ::http/allowed-origins {:creds true :allowed-origins (constantly true)}}) + :io.pedestal.http/join? false + :io.pedestal.http/allowed-origins {:creds true :allowed-origins (constantly true)}}) (pedestal/default-interceptors routing-interceptor) - http/dev-interceptors - http/create-server - http/start + io.pedestal.http/dev-interceptors + io.pedestal.http/create-server + io.pedestal.http/start (->> (reset! server))) (println "server running in port 3000")) -(start) +(comment + (start)) From 86fb0f72d021d574a85d099e8804740808866839 Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Fri, 31 Aug 2018 11:05:48 +0300 Subject: [PATCH 5/5] fix async code --- examples/pedestal/src/example/server.clj | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/examples/pedestal/src/example/server.clj b/examples/pedestal/src/example/server.clj index 05e55749..4b325981 100644 --- a/examples/pedestal/src/example/server.clj +++ b/examples/pedestal/src/example/server.clj @@ -9,6 +9,16 @@ {:enter (fn [ctx] (println ">>" x) ctx) :leave (fn [ctx] (println "<<" x) ctx)}) +(defn handler [_] + (println "handler") + {:status 200, + :body "pong"}) + +(def async-handler + {:enter (fn [{:keys [request] :as ctx}] + (a/go + (assoc ctx :response (handler request))))}) + (def routing-interceptor (pedestal/routing-interceptor (http/router @@ -19,19 +29,11 @@ ["/sync" {:interceptors [[interceptor :sync]] :get {:interceptors [[interceptor :get]] - :handler (fn [_] - (println "handler") - {:status 200, - :body "pong"})}}] + :handler handler}}] ["/async" {:interceptors [[interceptor :async]] - :get {:interceptors [[interceptor :get]] - :handler (fn [_] - (a/go - (println "handler") - {:status 200, - :body "pong"}))}}]] + :get {:interceptors [[interceptor :get] async-handler]}}]] {:data {:interceptors [[interceptor :router]]}}) (ring/create-default-handler) {:interceptors [[interceptor :top]]}))