Restrict http methods on RPC handlers

This commit is contained in:
Andrey Antukh 2024-03-05 19:06:29 +01:00
parent c3f37fb8a3
commit 07b8a2a6e6
2 changed files with 28 additions and 16 deletions

View file

@ -60,8 +60,12 @@
(defmethod handle-error :restriction (defmethod handle-error :restriction
[err _ _] [err _ _]
{::rres/status 400 (let [{:keys [code] :as data} (ex-data err)]
::rres/body (ex-data err)}) (if (= code :method-not-allowed)
{::rres/status 405
::rres/body data}
{::rres/status 400
::rres/body data})))
(defmethod handle-error :rate-limit (defmethod handle-error :rate-limit
[err _ _] [err _ _]

View file

@ -31,6 +31,7 @@
[app.util.services :as sv] [app.util.services :as sv]
[app.util.time :as dt] [app.util.time :as dt]
[clojure.spec.alpha :as s] [clojure.spec.alpha :as s]
[cuerdas.core :as str]
[integrant.core :as ig] [integrant.core :as ig]
[promesa.core :as p] [promesa.core :as p]
[ring.request :as rreq] [ring.request :as rreq]
@ -71,24 +72,31 @@
(defn- rpc-handler (defn- rpc-handler
"Ring handler that dispatches cmd requests and convert between "Ring handler that dispatches cmd requests and convert between
internal async flow into ring async flow." internal async flow into ring async flow."
[methods {:keys [params path-params] :as request}] [methods {:keys [params path-params method] :as request}]
(let [type (keyword (:type path-params)) (let [handler-name (:type path-params)
etag (rreq/get-header request "if-none-match") etag (rreq/get-header request "if-none-match")
profile-id (or (::session/profile-id request) profile-id (or (::session/profile-id request)
(::actoken/profile-id request)) (::actoken/profile-id request))
data (-> params data (-> params
(assoc ::request-at (dt/now)) (assoc ::request-at (dt/now))
(assoc ::session/id (::session/id request)) (assoc ::session/id (::session/id request))
(assoc ::cond/key etag) (assoc ::cond/key etag)
(cond-> (uuid? profile-id) (cond-> (uuid? profile-id)
(assoc ::profile-id profile-id))) (assoc ::profile-id profile-id)))
data (vary-meta data assoc ::http/request request) data (vary-meta data assoc ::http/request request)
method (get methods type default-handler)] handler-fn (get methods (keyword handler-name) default-handler)]
(when (and (or (= method :get)
(= method :head))
(not (str/starts-with? handler-name "get-")))
(ex/raise :type :restriction
:code :method-not-allowed
:hint "method not allowed for this request"))
(binding [cond/*enabled* true] (binding [cond/*enabled* true]
(let [response (method data)] (let [response (handler-fn data)]
(handle-response request response))))) (handle-response request response)))))
(defn- wrap-metrics (defn- wrap-metrics