duct-framework / duct

Server-side application framework for Clojure
MIT License
1.13k stars 51 forks source link

Docs for Duct middleware? #91

Closed teodorlu closed 5 years ago

teodorlu commented 5 years ago

Hello!

First off, I feel that Duct / Integrant has taught me something important about programming. The Clojure ecosystem is really good at emphasising the value of small building blocks of pure functions; bottom-up design is covered well. That leaves something to be said for top-down design. How to achieve a component based system where each component can be developed in as much isloation as possible, without incurring fragile glue code for system assembly. Thanks for that!

Onto the question -- are there docs I can read to understand Duct's approach to middleware?

Specifically, I'm trying to add a cross-origin header to a handler in an Ataraxy route. I've seen that there's a :middleware key under :duct.core/handler, which I assume will be "global" middleware. I'm saying this just for context -- I don't expect you to explain this here, I have some more research to do myself.

Teodor

teodorlu commented 5 years ago

Quick note: Currently reading 1 and 2, which may solve my problem in the specific case. So you might want to hold off on writing a huge reply! I'll report back later. Still haven't got a handle on this.

Quick note 2: Just found the guide, which was really helpful.

weavejester commented 5 years ago

The docs definitely need work, but I've unfortunately I've had trouble finding the time to improve it.

The :middleware key under :duct.handler/root (which replaces :duct.core/handler) is global middleware. You can see the implementation is pretty simple.

Ataraxy allows middleware to be placed on specific routes through metadata. The README for that project should document how middleware works in Ataraxy.

teodorlu commented 5 years ago

Ah, so it was the Ataraxy docs I should have been reading. Thanks for the link.

Do you think it's possible for anyone other than you to do docs work, or would that be hard without having the full context?


If anyone else are reading at a later time, I got this working both as a global middleware or a route-specific middleware (as suggested). Implementation below.

;; in file: pl/nostra/service/middleware/simulate.clj
(defmethod ig/init-key :pl.nostra.service.middleware/simulate [_ options]
  (prn :middleware/options options)
  (fn [handler]
    (prn :middleware/handler handler)
    (fn [request]
      (prn :middleware/request)
      (let [response (handler request)]
        (prn :middleware/response)
        response))))

;; global middleware
;; in file: config.edn
{:duct.profile/base
 {:duct.core/project-ns pl.nostra.service

  :duct.router/ataraxy
  {:routes {[:get "/simulate"] [:pl.nostra.service.handler/simulate]}}

  :duct.handler/root {:middleware [#ig/ref :pl.nostra.service.middleware/simulate]}

  :pl.nostra.service.middleware/simulate {}
  :pl.nostra.service.handler/simulate {}}

 ;; ...
}

;; route-local middleware
;; in file: config.edn
{:duct.profile/base
 {:duct.core/project-ns pl.nostra.service

  :duct.router/ataraxy
  {:routes {[:get "/simulate"] ^:simulate-middleware [:pl.nostra.service.handler/simulate]}
   :middleware {:simulate-middleware #ig/ref :pl.nostra.service.middleware/simulate}}

  :pl.nostra.service.middleware/simulate {}
  :pl.nostra.service.handler/simulate {}}

 ;; ...
}
teodorlu commented 5 years ago

I'm closing this, since I was able to do what I wanted to. If you do want help writing docs from someone else, I might be able to provide a beginner's perspective. I may also learn something from the experience!

Thanks again.

weavejester commented 5 years ago

Thank you. Help on the docs would be appreciated, if you wanted to add something to the wiki, or update the information already there.