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

Strategie a AI jako klíč. Do Prahy přijely špičky technologického světa

WebExpo 2025 ukázalo, jak se tvoří budoucnost. Třídenní technologická konference WebExpo 2025 přivedla do Prahy světové i české experty, kteří nabídli inspiraci napříč obory. Hlavním tématem byla propojenost disciplín, význam AI a potřeba otevřenosti vůči novým výzvám – včetně podpory legální imigrace. Ukázalo se, že inovace vznikají nejen v Silicon Valley, ale i tam, kde se nebojíme myslet jinak.

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ů.