Přejít k navigační liště

Zdroják » Různé » Ring Middleware

Ring Middleware

Články Různé

V minulém článku jsme se podívali na úplně nejzákladnější základy webového vývoje v Clojure – jak zpracovat HTTP request a response pomocí knihovny Ring. Tu nejzajímavější část Ringu – Middleware – jsme ale zmínili jen letmo a byla by škoda se do tohoto zajímavého konceptu trochu více neponořit.

Nálepky:

Text vyšel původně na autorově blogu.

Připomenutí základních konceptů

Než zrychlíme z 0 na 100, připomenu čtyři základní komponenty Ringu:

  • Handler – funkce, která přijímá mapu reprezentující HTTP request a vrací mapu představující HTTP response.
  • Request – mapa reprezentující HTTP request, která obsahuje sadu „standardních“ klíčů, které nám budou povědomé ze Servletu: :server-port, :server-name, :remote-address, :request-method ad.
  • Response – mapa, představující HTTP response, která obsahuje tři klíče: :status, :header, :body.
  • Middleware – funkce, která handleru přidá dodatečné funkcionality. Věci jako session, cookies či parametry jsou řešené middlewarem.

Anatomie Middlewaru

Middleware je funkce vyššího řádu, která přijímá jako parameter handler a vrací jiný handler (jako anonymní funkci), který nějakým způsobem obohatil buď request, nebo response. V podstatě se dá na middleware nahlížet jako na takový funkcionální decorator.

Pokud se podíváme na obecnou podobu middlewaru, má často následující strukturu (kudos to StackOverflow):

(defn wrap-blank-middleware
  "Blank middleware demonstrating common structure."
  [handler]
  (fn [request]
    ; Do some magic with the request
    (let [response (handler request)]
      ; Do some magic with the response
      ; and return the response.
      response)))

Balení middlewaru

Middleware většinou bývá jenom velmi jednoduchá funkce, takže komplexnější chování dostaneme zřetězením jednotlivých middlewarů, a to tak, že je postupně zabalujeme do sebe:

Způsob, jak middlewary do sebe zabalit, je dvojí – buď klasické zanořené funkce, nebo častější způsob je pomocí thread-first makra (->):

; "Classical" middleware wrapping
(middleware-3 (middleware-2 (middleware-1 handler)))

; Middleware wrapping via threading macro
(-> handler (middleware-1) (middleware-2) (middleware-3))

A jen pro úplnost – zabalit se anglicky řekne „wrap“, proto se používá konvence, že middlewary začínají prefixem wrap-.

Ilustrační příklad

Řekněme, že bychom psali RESTovou službu, která přijímá data pomocí PUT. Pomineme funkční logiku, zpracování dat i routování a soustředíme se jen na middleware, který se bude chovat následovně:

  • Pokud request metoda není PUT, vrátí middleware status 405 a text „Method Not Allowed“.
  • Pokud je request metoda PUT, vrátí status 204 (No Content) a prázdné body.

Aby middlewary byly malé a znovupoužitelné, rozdělíme si každou funkčnost, popsanou v předešlých odrážkách, do samostatné funkce:

  • wrap-no-content bude vracet status 204 a prázdné body.
  • wrap-put-allowed vrátí buď 405 (a popis v body), pokud metoda není PUT, nebo jenom zavolá původní handler.
(defn wrap-no-content
  "Middleware that returns a 204 No Content
  from the wrapped handler."
  [handler]
  (fn [request]
    (let [response (handler request)]
      (-> response
          (assoc :status 204)
          (dissoc :body)))))

(defn wrap-put-allowed
  "Middleware that returns a 405 Method Not Allowed
  if the request doesn't have :put method."
  [handler]
  (fn [request]
    (if (= (:request-method request) :put)
      (handler request)
      (let [response (handler request)]
        (-> response
            (assoc :status 405)
            (assoc :body "Method Not Allowed"))))))

 

Teď už stačí jen dát tyto dva middlewary dohromady, abychom dostali požadované chování:

(defn wrap-put-no-content
  "Middleware that returns a 204 No Content
  if the request method is PUT, otherwise
  a 405 Method Not Allowed."
  [handler]
  (-> handler
      (wrap-no-content)
      (wrap-put-allowed)))

GitHub projekt

Pokud vám výše popsané principy neštymují dohromady, mrkněte na GitHub, kde je malý spustitelný projektík, plus pár middleware unit testů:

Co příště?

O Ringu a jeho middlewarech by se dalo psát ještě dlouho, ale je čas pokročit. Logicky následným tématem je Compojure – routovací knihovna pro Ring webové aplikace.

Komentáře

Odebírat
Upozornit na
guest
0 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
Zobrazit všechny komentáře

Přístupnost není jen o splnění norem: nový pohled na inkluzivní design

Přístupnost a inkluze možná nepatří mezi nejžhavější témata digitálního světa – dokud o nich nezačne mluvit Vitaly Friedman. Na WebExpo 2024 předvedl, že inkluzivní design není jen o splněných checkboxech, ale hlavně o lidech. S energií sobě vlastní obrátil zažité přístupy naruby a ukázal, že skutečně přístupný web je nejen možný, ale i nezbytný.

Efektivnější vývoj UI nebo API: Co si odnést z WebExpo 2025?

Různé
Komentáře: 0
Jak snadno implementovat moderní uživatelské rozhraní? Které funkce brzdí rychlost vašeho webu? A kdy raději sami přibrzdit, abychom využitím AI nepřekročili etické principy? Debatu aktuálních dev témat rozdmýchá sedmnáctý ročník technologické konference WebExpo, která proběhne v Praze od 28. do 30. května. Který talk či workshop si rozhodně nenechat ujít? Toto je náš redakční výběr z vývojářských hroznů.

Zapřáhněte AI jako nikdy předtím. Květnová konference WebExpo přivítá hvězdy technologického světa

Od 28. do 30. května 2025 promění pražský Palác Lucerna na tři dny technologická konference WebExpo. Na programu je více než 80 přednášek a workshopů od expertů z celého světa. WebExpo tradičně propojuje vývojáře, designéry, marketéry i byznysové lídry a nabízí praktické dovednosti, strategické myšlení a přináší nejnovější trendy nejen v oblasti AI.