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

Cesta URL: co se děje, než se načte webová stránka

Když do adresního řádku prohlížeče napíšete webovou adresu a stisknete Enter, spustí se fascinující řetězec procesů, které propojují váš počítač s celým světem. Od překladu doménového jména na IP adresu, přes navázání šifrovaného spojení, až po vykreslení každého pixelu na obrazovce - to všechno se odehraje během zlomků sekundy. Pojďme se podívat, co se mezitím děje pod kapotou webu.

Stav SIMD v Rustu v roce 2025

Různé
Komentáře: 1
SIMD - neboli Single Instruction, Multiple Data - znamená, že procesor může jednou instrukcí zpracovat více datových prvků najednou. Typicky to znamená, že místo sčítání dvou čísel přičtete dvě sady čísel paralelně. To může přinést výrazné zrychlení například při zpracování obrazu, audia nebo numerických výpočtů. Pokud již SIMD znáte, tato tabulka je vše, co budete potřebovat. A pokud s SIMD teprve začínáte, tabulku pochopíte do konce tohoto článku