Skip to content

Commit

Permalink
Raamwerk overhaul
Browse files Browse the repository at this point in the history
Reitit everywhere
  • Loading branch information
danielsz committed Aug 5, 2023
1 parent d92f17e commit c06973a
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 182 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.org
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
* Changes
** 0.4.9-SNAPSHOT
- Raamwerk framework overhaul. Adoption of reitit as routing library. No need for middleware component, and handler component is greatly simplified.
- Undertow web server
** 0.4.8
- Mariadb: data-source and connection
Expand Down
4 changes: 2 additions & 2 deletions deps.edn
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{:deps {prismatic/schema {:mvn/version "1.4.1"}
org.danielsz/lang-utils {:mvn/version "0.1.4"}
org.clojure/tools.namespace {:mvn/version "1.3.0"}
io.aviso/pretty {:mvn/version "1.3"}
org.clojure/tools.namespace {:mvn/version "1.4.4"}
io.aviso/pretty {:mvn/version "1.4.4"}
com.stuartsierra/component {:mvn/version "1.1.0"}}}
4 changes: 2 additions & 2 deletions src/system/components/endpoint.clj
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
(ns system.components.endpoint
(:require [com.stuartsierra.component :as component]))

(defrecord Endpoint [routes-fn]
(defrecord Endpoint [f]
component/Lifecycle
(start [component]
(assoc component :routes (routes-fn component)))
(assoc component :routes (f component)))
(stop [component]
(dissoc component :routes)))

Expand Down
80 changes: 14 additions & 66 deletions src/system/components/handler.clj
Original file line number Diff line number Diff line change
@@ -1,81 +1,29 @@
(ns system.components.handler
(:require [com.stuartsierra.component :as component]
[lang-utils.core :refer [contains+?]]))
[reitit.core :as r]
[reitit.ring :as ring]))

(defn- endpoints
(defn merge-routers [& routers]
(ring/router
(apply merge (map r/routes routers))
(apply merge (map r/options routers))))

(defn endpoints
"Find all endpoints this component depends on, returns map entries of the form
[name component]. An endpoint is a component that define a `:routes` key."
[component]
(filter (comp :routes val) component))

(defn- with-middleware
"Returns all endpoints that include middleware. With `flag` being false:
returns all enpoints that *don't* include middleware. Works on [name
component] map entry pairs."
([endpoints]
(with-middleware endpoints true))
([endpoints flag]
(let [f (if flag
(fn [[k v]] (contains+? v :middleware))
(fn [[k v]] (not (contains+? v :middleware))))]
(filter f endpoints))))

(defn- middleware-key
"Given the endpoint map-entry this returns the key of the
middleware dependency if any, or an empty map."
[endpoint]
(reduce-kv (fn [_ k v] (if (contains+? v :middleware) (reduced k) _)) {} (val endpoint)))

(defrecord Handler [router shared-root-middleware?]
(defrecord Handler [default-handler options]
component/Lifecycle
(start [component]
(let [endpoints-with-middleware (partition-by middleware-key ((comp with-middleware endpoints) component))
handlers (for [endpoints endpoints-with-middleware
:let [mw-key (middleware-key (first endpoints))
wrap-mw (get-in (val (first endpoints)) [mw-key :wrap-mw])
routes (keep :routes (vals endpoints))]]
(wrap-mw (apply router routes)))
routes (keep :routes (vals (-> component
endpoints
(with-middleware false))))
wrap-mw (get-in component [:middleware :wrap-mw] identity)
handler (if shared-root-middleware?
(wrap-mw (apply router (concat routes handlers)))
(apply router (reverse (conj routes (wrap-mw (apply router handlers))))))]
(let [routes (map :routes (vals (endpoints component)))
routers (apply merge-routers routes)
handler (ring/ring-handler routers (default-handler component) options)]
(assoc component :handler handler)))
(stop [component]
(dissoc component :handler)))

(defn new-handler
"Creates a handler component. A handler component combines endpoints and
middleware into a ring handler function.
Endpoints should be added as dependencies using `component/using`, the names
used for endpoints don't matter, they are recognized by their structure.
Middleware can be added by depending on a middleware component, either
per-endpoint, or once for the complete handler. Per-endpoint middleware can
use any name, middleware on the handler must be called `:middleware`.
An optional `router` parameter allows you to specify the routing
library. At the moment, one of `:compojure` or `:bidi`.
The resulting ring handler function is available as `:handler` on the handler
component.
Example:
(component/system-map
:endpoint-a (new-endpoint some-routes)
:endpoint-b (-> (new-endpoint other-routes)
(component/using [:endpoint-b-middleware]))
:endpoint-b-middleware (new-middleware {:middleware [,,,]})
:middleware (new-middleware {:middleware [,,,]})
:handler (-> (new-handler)
(component/using [:endpoint-a :endpoint-b :middleware]))
:jetty (-> (new-web-server port)
(component/using [:handler])))"
[& {:keys [router shared-root-middleware?] :or {router :compojure shared-root-middleware? true}}]
(let [routers {:compojure #(ns-resolve 'compojure.core (symbol "routes"))
:bidi #(ns-resolve 'bidi.ring (symbol "make-handler"))}]
(map->Handler {:router ((router routers)) :shared-root-middleware? shared-root-middleware?})))
[& {:keys [default-handler options]}]
(map->Handler {:default-handler default-handler :options options}))
70 changes: 0 additions & 70 deletions src/system/components/middleware.clj

This file was deleted.

67 changes: 28 additions & 39 deletions src/system/components/sente.cljc
Original file line number Diff line number Diff line change
@@ -1,72 +1,61 @@
(ns system.components.sente
#?(:clj
(:require [com.stuartsierra.component :as component]
[compojure.core :refer [routes GET POST]]
[reitit.ring :as r]
[taoensso.sente :as sente]
[ring.util.response :as ring]
[clojure.tools.logging :as log])
:cljs
(:require [com.stuartsierra.component :as component]
[taoensso.sente :as sente])))


#?(:clj
(defn sente-routes [{{ring-ajax-post :ring-ajax-post ring-ajax-get-or-ws-handshake :ring-ajax-get-or-ws-handshake} :sente}]
(routes
(GET "/chsk" req (try
(ring-ajax-get-or-ws-handshake req)
(catch clojure.lang.ExceptionInfo e
(log/error (ex-data e))
(-> (ring/response "")
(ring/status 400)))))
(POST "/chsk" req (ring-ajax-post req)))))
(defn sente-routes [{{ring-ajax-post :ring-ajax-post ring-ajax-get-or-ws-handshake :ring-ajax-get-or-ws-handshake middleware :middleware} :sente}]
(r/router ["/chsk" (cond-> {:get (fn [req] (try
(ring-ajax-get-or-ws-handshake req)
(catch clojure.lang.ExceptionInfo e
(log/error (ex-data e))
(-> (ring/response (.getMessage e))
(ring/status 400)))))
:post (fn [req] (ring-ajax-post req))}
(some? middleware) (assoc :middleware middleware))])))


;; Sente supports both CLJ and CLJS as a server
(defrecord ChannelSocketServer [web-server-adapter handler options]
(defrecord ChannelSocketServer [handler adapter options middleware]
component/Lifecycle
(start [component]
(let [handler (get-in component [:sente-handler :handler] handler)
{:keys [ch-recv ajax-post-fn ajax-get-or-ws-handshake-fn send-fn connected-uids]} (sente/make-channel-socket-server! web-server-adapter options)]
(let [{:keys [ch-recv ajax-post-fn ajax-get-or-ws-handshake-fn send-fn connected-uids]} (sente/make-channel-socket-server! adapter options)]
(assoc component
:ch-chsk ch-recv
:ring-ajax-post ajax-post-fn
:ring-ajax-get-or-ws-handshake ajax-get-or-ws-handshake-fn
:chsk-send! send-fn
:connected-uids connected-uids
:router (sente/start-chsk-router! ch-recv (if (:wrap-component? options)
(handler component)
handler)))))
:router (sente/start-chsk-router! ch-recv (handler component)))))
(stop [component]
(when-let [stop-f (:router component)]
(stop-f))
component))

(defn new-channel-socket-server
([web-server-adapter]
(new-channel-socket-server nil web-server-adapter {}))
([event-msg-handler web-server-adapter]
(new-channel-socket-server event-msg-handler web-server-adapter {}))
([event-msg-handler web-server-adapter options]
(map->ChannelSocketServer {:web-server-adapter web-server-adapter
:handler event-msg-handler
:options options})))

;; Old fn name
(def new-channel-sockets new-channel-socket-server)
(defn new-channel-socket-server [& {:keys [handler adapter options middleware]}]
(map->ChannelSocketServer {:handler handler
:adapter adapter
:options options
:middleware middleware}))

;; Sente does not support CLJ as a client yet
#?(:cljs
(defrecord ChannelSocketClient [path csrf-token options]
component/Lifecycle
(start [component]
(let [handler (get-in component [:sente-handler :handler])
{:keys [chsk ch-recv send-fn state]} (sente/make-channel-socket-client! path csrf-token options)
component (assoc component
:chsk chsk
:ch-chsk ch-recv ; ChannelSocket's receive channel
:chsk-send! send-fn ; ChannelSocket's send API fn
:chsk-state state)]
(if handler
(assoc component :router (sente/start-chsk-router! ch-recv handler))
component)))
(let [{:keys [chsk ch-recv send-fn state]} (sente/make-channel-socket-client! path csrf-token options)]
(assoc component
:chsk chsk
:ch-chsk ch-recv ; ChannelSocket's receive channel
:chsk-send! send-fn ; ChannelSocket's send API fn
:chsk-state state)))
(stop [component]
(when-let [chsk (:chsk component)]
(sente/chsk-disconnect! chsk))
Expand All @@ -84,7 +73,7 @@
([csrf-token]
(new-channel-socket-client "/chsk" csrf-token))
([path csrf-token]
(new-channel-socket-client path csrf-token {}))
(new-channel-socket-client path csrf-token {:type :auto}))
([path csrf-token options]
(map->ChannelSocketClient {:path path
:csrf-token csrf-token
Expand Down
7 changes: 4 additions & 3 deletions src/system/components/undertow.clj
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
(ns system.components.undertow
(:require [ring.adapter.undertow :refer [run-undertow]]
[com.stuartsierra.component :as component]
[lang-utils.core :refer [seek]]))
[com.stuartsierra.component :as component]))

(defrecord WebServer [handler options]
component/Lifecycle
(start [component]
(let [handler (if (fn? handler) handler (:handler (val (seek (comp :handler val) component))))
(let [handler (if (fn? handler)
handler
(get-in component [:handler :handler]))
server (run-undertow handler options)]
(assoc component :server server)))
(stop [component]
Expand Down

0 comments on commit c06973a

Please sign in to comment.