mirror of
https://github.com/penpot/penpot.git
synced 2026-05-02 22:58:35 +00:00
- makes the profile access more efficient (replace in-app joins to a simple select query on profile table - add partial support for access-tokens (still missing some RPC methods) - move router definitions to specific modules and simplify the main http module definitions to simple includes - simplifiy authentication code related to access-tokens and sessions - normalize db parameters with proper namespaced props - more work on convert all modules initialization to use proper specs with fully-qualified keyword config props
162 lines
5.1 KiB
Clojure
162 lines
5.1 KiB
Clojure
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
;;
|
|
;; Copyright (c) KALEIDOS INC
|
|
|
|
(ns app.http
|
|
(:require
|
|
[app.auth.oidc :as-alias oidc]
|
|
[app.common.data :as d]
|
|
[app.common.logging :as l]
|
|
[app.common.transit :as t]
|
|
[app.db :as-alias db]
|
|
[app.http.access-token :as actoken]
|
|
[app.http.assets :as-alias assets]
|
|
[app.http.awsns :as-alias awsns]
|
|
[app.http.debug :as-alias debug]
|
|
[app.http.errors :as errors]
|
|
[app.http.middleware :as mw]
|
|
[app.http.session :as session]
|
|
[app.http.websocket :as-alias ws]
|
|
[app.metrics :as mtx]
|
|
[app.rpc :as-alias rpc]
|
|
[app.rpc.doc :as-alias rpc.doc]
|
|
[app.worker :as wrk]
|
|
[clojure.spec.alpha :as s]
|
|
[integrant.core :as ig]
|
|
[reitit.core :as r]
|
|
[reitit.middleware :as rr]
|
|
[yetti.adapter :as yt]
|
|
[yetti.request :as yrq]
|
|
[yetti.response :as yrs]))
|
|
|
|
(declare wrap-router)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; HTTP SERVER
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(s/def ::handler fn?)
|
|
(s/def ::router some?)
|
|
(s/def ::port integer?)
|
|
(s/def ::host string?)
|
|
(s/def ::name string?)
|
|
|
|
(s/def ::max-body-size integer?)
|
|
(s/def ::max-multipart-body-size integer?)
|
|
(s/def ::io-threads integer?)
|
|
(s/def ::worker-threads integer?)
|
|
|
|
(defmethod ig/prep-key ::server
|
|
[_ cfg]
|
|
(merge {:name "http"
|
|
:port 6060
|
|
:host "0.0.0.0"
|
|
:max-body-size (* 1024 1024 30) ; 30 MiB
|
|
:max-multipart-body-size (* 1024 1024 120)} ; 120 MiB
|
|
(d/without-nils cfg)))
|
|
|
|
(defmethod ig/pre-init-spec ::server [_]
|
|
(s/and
|
|
(s/keys :req-un [::port ::host ::name ::max-body-size ::max-multipart-body-size]
|
|
:opt-un [::router ::handler ::io-threads ::worker-threads ::wrk/executor])
|
|
(fn [cfg]
|
|
(or (contains? cfg :router)
|
|
(contains? cfg :handler)))))
|
|
|
|
(defmethod ig/init-key ::server
|
|
[_ {:keys [handler router port name host] :as cfg}]
|
|
(l/info :hint "starting http server" :port port :host host :name name)
|
|
(let [options {:http/port port
|
|
:http/host host
|
|
:http/max-body-size (:max-body-size cfg)
|
|
:http/max-multipart-body-size (:max-multipart-body-size cfg)
|
|
:xnio/io-threads (:io-threads cfg)
|
|
:xnio/dispatch (:executor cfg)
|
|
:ring/async true}
|
|
|
|
handler (if (some? router)
|
|
(wrap-router router)
|
|
|
|
handler)
|
|
server (yt/server handler (d/without-nils options))]
|
|
(assoc cfg :server (yt/start! server))))
|
|
|
|
(defmethod ig/halt-key! ::server
|
|
[_ {:keys [server name port] :as cfg}]
|
|
(l/info :msg "stopping http server" :name name :port port)
|
|
(yt/stop! server))
|
|
|
|
(defn- not-found-handler
|
|
[_ respond _]
|
|
(respond (yrs/response 404)))
|
|
|
|
(defn- wrap-router
|
|
[router]
|
|
(letfn [(handler [request respond raise]
|
|
(if-let [match (r/match-by-path router (yrq/path request))]
|
|
(let [params (:path-params match)
|
|
result (:result match)
|
|
handler (or (:handler result) not-found-handler)
|
|
request (assoc request :path-params params)]
|
|
(handler request respond raise))
|
|
(not-found-handler request respond raise)))
|
|
|
|
(on-error [cause request respond]
|
|
(let [{:keys [body] :as response} (errors/handle cause request)]
|
|
(respond
|
|
(cond-> response
|
|
(map? body)
|
|
(-> (update :headers assoc "content-type" "application/transit+json")
|
|
(assoc :body (t/encode-str body {:type :json-verbose})))))))]
|
|
|
|
(fn [request respond _]
|
|
(try
|
|
(handler request respond #(on-error % request respond))
|
|
(catch Throwable cause
|
|
(on-error cause request respond))))))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; HTTP ROUTER
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(defmethod ig/pre-init-spec ::router [_]
|
|
(s/keys :req [::session/manager
|
|
::actoken/manager
|
|
::ws/routes
|
|
::rpc/routes
|
|
::rpc.doc/routes
|
|
::oidc/routes
|
|
::assets/routes
|
|
::debug/routes
|
|
::db/pool
|
|
::mtx/routes
|
|
::awsns/routes]))
|
|
|
|
(defmethod ig/init-key ::router
|
|
[_ cfg]
|
|
(rr/router
|
|
[["" {:middleware [[mw/server-timing]
|
|
[mw/format-response]
|
|
[mw/params]
|
|
[mw/parse-request]
|
|
[session/soft-auth cfg]
|
|
[actoken/soft-auth cfg]
|
|
[mw/errors errors/handle]
|
|
[mw/restrict-methods]]}
|
|
|
|
(::mtx/routes cfg)
|
|
(::assets/routes cfg)
|
|
(::debug/routes cfg)
|
|
|
|
["/webhooks"
|
|
(::awsns/routes cfg)]
|
|
|
|
(::ws/routes cfg)
|
|
|
|
["/api" {:middleware [[mw/cors]]}
|
|
(::oidc/routes cfg)
|
|
(::rpc.doc/routes cfg)
|
|
(::rpc/routes cfg)]]]))
|