Merge pull request #133 from metosin/pedestal

Pedestal-example
This commit is contained in:
Tommi Reiman 2018-08-31 11:09:49 +03:00 committed by GitHub
commit 5703b5dc60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 169 additions and 2 deletions

11
examples/pedestal/.gitignore vendored Normal file
View file

@ -0,0 +1,11 @@
/target
/classes
/checkouts
pom.xml
pom.xml.asc
*.jar
*.class
/.lein-*
/.nrepl-port
.hgignore
.hg/

View file

@ -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

View file

@ -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.4"]
[io.pedestal/pedestal.jetty "0.5.4"]
[metosin/reitit "0.2.0-SNAPSHOT"]]
:repl-options {:init-ns example.server})

View file

@ -0,0 +1,63 @@
(ns example.server
(:require [io.pedestal.http]
[clojure.core.async :as a]
[reitit.pedestal :as pedestal]
[reitit.http :as http]
[reitit.ring :as ring]))
(defn interceptor [x]
{: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
["/api"
{:interceptors [[interceptor :api]
[interceptor :apa]]}
["/sync"
{:interceptors [[interceptor :sync]]
:get {:interceptors [[interceptor :get]]
:handler handler}}]
["/async"
{:interceptors [[interceptor :async]]
:get {:interceptors [[interceptor :get] async-handler]}}]]
{:data {:interceptors [[interceptor :router]]}})
(ring/create-default-handler)
{:interceptors [[interceptor :top]]}))
(defonce server (atom nil))
(defn start []
(when @server
(io.pedestal.http/stop @server)
(println "server stopped"))
(-> {:env :prod
:io.pedestal.http/routes []
:io.pedestal.http/resource-path "/public"
:io.pedestal.http/type :jetty
:io.pedestal.http/port 3000}
(merge {:env :dev
:io.pedestal.http/join? false
:io.pedestal.http/allowed-origins {:creds true :allowed-origins (constantly true)}})
(pedestal/default-interceptors routing-interceptor)
io.pedestal.http/dev-interceptors
io.pedestal.http/create-server
io.pedestal.http/start
(->> (reset! server)))
(println "server running in port 3000"))
(comment
(start))

View file

@ -0,0 +1,38 @@
(ns reitit.pedestal
(:require [io.pedestal.interceptor.chain :as chain]
[io.pedestal.interceptor :as interceptor]
[io.pedestal.http :as http]
[reitit.interceptor]
[reitit.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 {:keys [interceptors]}]
(interceptor/interceptor
(reitit.http/routing-interceptor
router
default-handler
{:executor pedestal-executor
:interceptors interceptors}))))
(defn default-interceptors [spec router]
(-> spec
(assoc ::http/routes [])
(http/default-interceptors)
(update ::http/interceptors (comp vec butlast))
(update ::http/interceptors conj router)))

View file

@ -18,7 +18,10 @@
(execute (execute
[this interceptors request] [this interceptors request]
[this interceptors request respond raise] [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] (defn context [request]
(map->Context {:request request})) (map->Context {:request request}))

View file

@ -61,6 +61,33 @@
(let [opts (meta-merge {:coerce coerce-handler, :compile compile-result} opts)] (let [opts (meta-merge {:coerce coerce-handler, :compile compile-result} opts)]
(r/router data 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 (defn ring-handler
"Creates a ring-handler out of a http-router, "Creates a ring-handler out of a http-router,
a default ring-handler and options map, with the following keys: a default ring-handler and options map, with the following keys:

View file

@ -81,7 +81,8 @@
:dependencies [[compojure "1.6.1"] :dependencies [[compojure "1.6.1"]
[ring/ring-defaults "0.3.2"] [ring/ring-defaults "0.3.2"]
[ikitommi/immutant-web "3.0.0-alpha1"] [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"] [org.clojure/core.async "0.4.474"]
[metosin/sieppari "0.0.0-alpha4"] [metosin/sieppari "0.0.0-alpha4"]
[yada "1.2.13"] [yada "1.2.13"]