mirror of
https://github.com/penpot/penpot.git
synced 2025-01-08 16:00:19 -05:00
♻️ Replace interceptors with middleware on vertx package.
This commit is contained in:
parent
3507c4acb6
commit
fd6362e463
7 changed files with 115 additions and 119 deletions
25
backend/vendor/vertx/README.md
vendored
25
backend/vendor/vertx/README.md
vendored
|
@ -75,6 +75,7 @@ The `deploy!` function also accepts an additional parameter for
|
|||
options, and at this momment it only accepts as single option:
|
||||
|
||||
- `:instances` - number of instances to launch of the same verticle.
|
||||
- `:worker` - use worker thread pool or the default event-loop.
|
||||
|
||||
|
||||
### Event Bus
|
||||
|
@ -196,7 +197,7 @@ Lets start with a complete example:
|
|||
```clojure
|
||||
(require '[vertx.http :as vh])
|
||||
(require '[vertx.web :as vw])
|
||||
(require '[vertx.web.interceptors :as vwi])
|
||||
(require '[vertx.web.middleware :as vwm])
|
||||
|
||||
(defn hello-world-handler
|
||||
[req]
|
||||
|
@ -205,8 +206,9 @@ Lets start with a complete example:
|
|||
|
||||
(defn on-start
|
||||
[ctx]
|
||||
(let [routes [["/" {:interceptors [(vwi/cookies)]
|
||||
:all hello-world-handler}]]
|
||||
(let [routes [["/" {:middleware [vwm/cookies]
|
||||
:handler hello-world-handler
|
||||
:method :get}]]
|
||||
handler (vw/handler ctx
|
||||
(vw/assets "/static/*" {:root "resources/public/static"})
|
||||
(vw/router routes))]
|
||||
|
@ -217,25 +219,24 @@ Lets start with a complete example:
|
|||
(vc/deploy! system))
|
||||
```
|
||||
|
||||
The routes are defined using `reitit-core` and the interceptors are
|
||||
using `sieppari` as underlying implementation. The request object is
|
||||
very similar to the one explained in `vertx.http`.
|
||||
The routes are defined using `reitit-core`. The request object is very
|
||||
similar to the one explained in `vertx.http`.
|
||||
|
||||
The main difference with `vertx.http` is that the handler is called
|
||||
when the body is ready to be used and is available under `:body`
|
||||
keyword on the request.
|
||||
|
||||
All additional features such that reading the query/form params,
|
||||
parse/write cookies, cors and file uploads are provided with
|
||||
interceptors as pluggable pieces:
|
||||
parse/write cookies, cors and file uploads are provided with additional middleware
|
||||
wrappers:
|
||||
|
||||
- `vertx.web.interceptors/uploads` parses the vertx uploaded file data
|
||||
- `vertx.web.middleware/uploads` parses the vertx uploaded file data
|
||||
structure and expose it as clojure maps under `:uploads` key.
|
||||
- `vertx.web.interceptors/params` parses the query string and form
|
||||
- `vertx.web.middleware/params` parses the query string and form
|
||||
params in the body if the content-type is appropriate and exposes
|
||||
them under `:params`.
|
||||
- `vertx.web.interceptors/cors` properly sets the CORS headers.
|
||||
- `vertx.web.interceptors/cookies` handles the cookies reading from
|
||||
- `vertx.web.middleware/cors` properly sets the CORS headers.
|
||||
- `vertx.web.middleware/cookies` handles the cookies reading from
|
||||
the request and cookies writing from the response.
|
||||
|
||||
|
||||
|
|
1
backend/vendor/vertx/deps.edn
vendored
1
backend/vendor/vertx/deps.edn
vendored
|
@ -2,7 +2,6 @@
|
|||
{org.clojure/tools.logging {:mvn/version "0.5.0"}
|
||||
funcool/promesa {:mvn/version "5.0.0"}
|
||||
metosin/reitit-core {:mvn/version "0.3.10"}
|
||||
metosin/sieppari {:mvn/version "0.0.0-alpha8"}
|
||||
org.clojure/core.async {:mvn/version "0.7.559"}
|
||||
io.vertx/vertx-core {:mvn/version "4.0.0-milestone4"}
|
||||
io.vertx/vertx-web {:mvn/version "4.0.0-milestone4"}
|
||||
|
|
5
backend/vendor/vertx/pom.xml
vendored
5
backend/vendor/vertx/pom.xml
vendored
|
@ -57,11 +57,6 @@
|
|||
<artifactId>core.async</artifactId>
|
||||
<version>0.7.559</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>metosin</groupId>
|
||||
<artifactId>sieppari</artifactId>
|
||||
<version>0.0.0-alpha8</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
|
|
34
backend/vendor/vertx/src/vertx/web.clj
vendored
34
backend/vendor/vertx/src/vertx/web.clj
vendored
|
@ -10,8 +10,8 @@
|
|||
[clojure.tools.logging :as log]
|
||||
[clojure.spec.alpha :as s]
|
||||
[promesa.core :as p]
|
||||
[sieppari.core :as sp]
|
||||
[reitit.core :as rt]
|
||||
[reitit.middleware :as rmw]
|
||||
[vertx.http :as http]
|
||||
[vertx.impl :as impl])
|
||||
(:import
|
||||
|
@ -57,10 +57,7 @@
|
|||
|
||||
(defn handler
|
||||
"Wraps a user defined funcion based handler into a vertx-web aware
|
||||
handler (with support for multipart uploads.
|
||||
|
||||
If the handler is a vector, the sieppari intercerptos engine will be used
|
||||
to resolve the execution of the interceptors + handler."
|
||||
handler (with support for multipart uploads)."
|
||||
[vsm & handlers]
|
||||
(let [^Vertx vsm (impl/resolve-system vsm)
|
||||
^Router router (Router/router vsm)]
|
||||
|
@ -89,23 +86,13 @@
|
|||
{:status 500
|
||||
:body "Internal server error!\n"})
|
||||
|
||||
(defn- run-chain
|
||||
[ctx chain handler]
|
||||
(let [d (p/deferred)]
|
||||
(sp/execute (conj chain handler) ctx #(p/resolve! d %) #(p/reject! d %))
|
||||
d))
|
||||
|
||||
(defn- router-handler
|
||||
[router {:keys [path method] :as ctx}]
|
||||
(let [{:keys [data path-params] :as match} (rt/match-by-path router path)
|
||||
handler-fn (or (get data method)
|
||||
(get data :all)
|
||||
default-handler)
|
||||
interceptors (get data :interceptors)
|
||||
(if-let [{:keys [result path-params] :as match} (rt/match-by-path router path)]
|
||||
(let [handler-fn (:handler result)
|
||||
ctx (assoc ctx ::match match :path-params path-params)]
|
||||
(if (empty? interceptors)
|
||||
(handler-fn ctx)
|
||||
(run-chain ctx interceptors handler-fn))))
|
||||
(handler-fn ctx))
|
||||
(default-handler ctx)))
|
||||
|
||||
(defn router
|
||||
([routes] (router routes {}))
|
||||
|
@ -120,8 +107,8 @@
|
|||
log-requests? false
|
||||
time-response? true}
|
||||
:as options}]
|
||||
(let [rtr (rt/router routes options)
|
||||
f #(router-handler rtr %)]
|
||||
(let [rtr (rt/router routes {:compile rmw/compile-result})
|
||||
rtf #(router-handler rtr %)]
|
||||
(fn [^Router router]
|
||||
(let [^Route route (.route router)]
|
||||
(when time-response? (.handler route (ResponseTimeHandler/create)))
|
||||
|
@ -149,8 +136,9 @@
|
|||
(.put ^RoutingContext rc "vertx$clj$req" req)
|
||||
(.fail ^RoutingContext rc ^Throwable err))]
|
||||
(try
|
||||
(-> (http/-handle-response (f req) req)
|
||||
(p/catch' efn))
|
||||
(let [result (rtf req)]
|
||||
(-> (http/-handle-response result req)
|
||||
(p/catch' efn)))
|
||||
(catch Exception err
|
||||
(efn err)))))))))
|
||||
router))))
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
(:require
|
||||
[clojure.spec.alpha :as s]
|
||||
[promesa.core :as p]
|
||||
[sieppari.core :as sp]
|
||||
[reitit.core :as rt]
|
||||
[vertx.http :as http]
|
||||
[vertx.impl :as impl])
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
;;
|
||||
;; Copyright (c) 2019 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns vertx.web.interceptors
|
||||
"High level api for http servers."
|
||||
(ns vertx.web.middleware
|
||||
"Common middleware's."
|
||||
(:require
|
||||
[clojure.spec.alpha :as s]
|
||||
[clojure.string :as str]
|
||||
|
@ -13,9 +13,7 @@
|
|||
[reitit.core :as r]
|
||||
[vertx.http :as http]
|
||||
[vertx.web :as web]
|
||||
[vertx.util :as util]
|
||||
[sieppari.context :as spx]
|
||||
[sieppari.core :as sp])
|
||||
[vertx.util :as util])
|
||||
(:import
|
||||
clojure.lang.Keyword
|
||||
clojure.lang.MapEntry
|
||||
|
@ -41,24 +39,36 @@
|
|||
(:path data) (.setPath (:path data))
|
||||
(:secure data) (.setSecure true)))
|
||||
|
||||
(defn cookies
|
||||
[]
|
||||
{:enter
|
||||
(fn [data]
|
||||
(let [^HttpServerRequest req (get-in data [:request ::http/request])
|
||||
parse-cookie (fn [^Cookie item] [(.getName item) (.getValue item)])
|
||||
cookies (into {} (map parse-cookie) (vals (.cookieMap req)))]
|
||||
(update data :request assoc :cookies cookies)))
|
||||
:leave
|
||||
(fn [data]
|
||||
(let [cookies (get-in data [:response :cookies])
|
||||
^HttpServerResponse res (get-in data [:request ::http/response])]
|
||||
(when (map? cookies)
|
||||
(defn- handle-cookies-response
|
||||
[request {:keys [cookies] :as response}]
|
||||
(let [^HttpServerResponse res (::http/response request)]
|
||||
(util/doseq [[key val] cookies]
|
||||
(if (nil? val)
|
||||
(.removeCookie res key)
|
||||
(.addCookie res (build-cookie key val)))))
|
||||
data))})
|
||||
(.addCookie res (build-cookie key val))))))
|
||||
|
||||
(defn- cookie->vector
|
||||
[^Cookie item]
|
||||
[(.getName item) (.getValue item)])
|
||||
|
||||
(defn- wrap-cookies
|
||||
[handler]
|
||||
(let [xf (map cookie->vector)]
|
||||
(fn [request]
|
||||
(let [req (::http/request request)
|
||||
cookies (.cookieMap ^HttpServerRequest req)
|
||||
cookies (into {} xf (vals cookies))]
|
||||
(-> (p/do! (handler (assoc request :cookies cookies)))
|
||||
(p/then' (fn [response]
|
||||
(when (and (map? response)
|
||||
(map? (:cookies response)))
|
||||
(handle-cookies-response request response))
|
||||
response)))))))
|
||||
|
||||
(def cookies
|
||||
{:name ::cookies
|
||||
:compile (constantly wrap-cookies)})
|
||||
|
||||
|
||||
;; --- Params
|
||||
|
||||
|
@ -83,46 +93,54 @@
|
|||
(recur (assoc! m key [prv val]))))
|
||||
(persistent! m)))))
|
||||
|
||||
(defn params
|
||||
([] (params nil))
|
||||
([{:keys [attr] :or {attr :params}}]
|
||||
{:enter (fn [data]
|
||||
(let [request (get-in data [:request ::http/request])
|
||||
params (parse-params request)]
|
||||
(update data :request assoc attr params)))}))
|
||||
(defn- wrap-params
|
||||
[handler]
|
||||
(fn [request]
|
||||
(let [req (::http/request request)
|
||||
params (parse-params req)]
|
||||
(handler (assoc request :params params)))))
|
||||
|
||||
(def params
|
||||
{:name ::params
|
||||
:compile (constantly wrap-params)})
|
||||
|
||||
|
||||
;; --- Uploads
|
||||
|
||||
(defn uploads
|
||||
([] (uploads nil))
|
||||
([{:keys [attr] :or {attr :uploads}}]
|
||||
{:enter (fn [data]
|
||||
(let [context (get-in data [:request ::web/routing-context])
|
||||
(defn- wrap-uploads
|
||||
[handler]
|
||||
(fn [request]
|
||||
(let [rctx (::web/routing-context request)
|
||||
uploads (.fileUploads ^RoutingContext rctx)
|
||||
uploads (reduce (fn [acc ^FileUpload upload]
|
||||
(assoc! acc
|
||||
(assoc acc
|
||||
(keyword (.name upload))
|
||||
{:type :uploaded-file
|
||||
:mtype (.contentType upload)
|
||||
:path (.uploadedFileName upload)
|
||||
:name (.fileName upload)
|
||||
:size (.size upload)}))
|
||||
(transient {})
|
||||
(.fileUploads ^RoutingContext context))]
|
||||
(update data :request assoc attr (persistent! uploads))))}))
|
||||
{}
|
||||
uploads)]
|
||||
(handler (assoc request :uploads uploads)))))
|
||||
|
||||
(def uploads
|
||||
{:name ::uploads
|
||||
:compile (constantly wrap-uploads)})
|
||||
|
||||
;; --- Errors
|
||||
|
||||
(defn errors
|
||||
"A error handling interceptor."
|
||||
[handler-fn]
|
||||
{:error
|
||||
(fn [data]
|
||||
(let [request (:request data)
|
||||
error (:error data)
|
||||
response (handler-fn error request)]
|
||||
(-> data
|
||||
(assoc :response response)
|
||||
(dissoc :error))))})
|
||||
(defn- wrap-errors
|
||||
[handler on-error]
|
||||
(fn [request]
|
||||
(-> (p/do! (handler request))
|
||||
(p/catch (fn [error]
|
||||
(on-error error request))))))
|
||||
|
||||
(def errors
|
||||
{:name ::errors
|
||||
:compile (constantly wrap-errors)})
|
||||
|
||||
|
||||
;; --- CORS
|
||||
|
||||
|
@ -140,8 +158,8 @@
|
|||
::expose-headers
|
||||
::max-age]))
|
||||
|
||||
(defn cors
|
||||
[opts]
|
||||
(defn wrap-cors
|
||||
[handler opts]
|
||||
(s/assert ::cors-opts opts)
|
||||
(letfn [(preflight? [{:keys [method headers] :as ctx}]
|
||||
(and (= method :options)
|
||||
|
@ -184,19 +202,16 @@
|
|||
(:allow-headers opts)
|
||||
(assoc "access-control-allow-headers"
|
||||
(-> (normalize (:allow-headers opts))
|
||||
(str/lower-case))))))
|
||||
(str/lower-case))))))]
|
||||
(fn [request]
|
||||
(if (preflight? request)
|
||||
{:status 204 :headers (get-headers request)}
|
||||
(-> (p/do! (handler request))
|
||||
(p/then (fn [response]
|
||||
(if (map? response)
|
||||
(update response :headers merge (get-headers request))
|
||||
response))))))))
|
||||
|
||||
(enter [data]
|
||||
(let [ctx (:request data)]
|
||||
(if (preflight? ctx)
|
||||
(spx/terminate (assoc data ::preflight true))
|
||||
data)))
|
||||
|
||||
(leave [data]
|
||||
(let [headers (get-headers (:request data))]
|
||||
(if (::preflight data)
|
||||
(assoc data :response {:status 204 :headers headers})
|
||||
(update-in data [:response :headers] merge headers))))]
|
||||
|
||||
{:enter enter
|
||||
:leave leave}))
|
||||
(def cors
|
||||
{:name ::cors
|
||||
:compile (constantly wrap-cors)})
|
3
backend/vendor/vertx/test/user.clj
vendored
3
backend/vendor/vertx/test/user.clj
vendored
|
@ -12,8 +12,7 @@
|
|||
[vertx.core :as vc]
|
||||
[vertx.eventbus :as ve]
|
||||
[vertx.http :as vh]
|
||||
[vertx.web :as vw]
|
||||
[vertx.web.interceptors :as vwi])
|
||||
[vertx.web :as vw])
|
||||
(:import
|
||||
io.vertx.core.http.HttpServerRequest
|
||||
io.vertx.core.http.HttpServerResponse))
|
||||
|
|
Loading…
Reference in a new issue