Here's my suggestion instead, break out your pure and impure behavior. Don't design it so that you inject the behavior, instead seperate them into independent units and compose them at the handler.
(defn get-article-id
[request]
(get-in request [:path-params :id]))
(defn make-response
[status body]
{:status status
:body body})
(defn get-article!
[data-source request]
(->> request
(get-article-id)
(db/get-article-by-id! data-source)
(make-response 200)))
This is often known as the Functional Core, Imperative Shell pattern. The functional core cannot call out to the imperative shell.