Web Development

39.1 Ring: The HTTP Abstraction

;; A Ring handler is a function: request map → response map
(defn handler [request]
  {:status 200
   :headers {"Content-Type" "text/plain"}
   :body (str "Hello from " (:uri request))})

;; Middleware: functions that wrap handlers
(defn wrap-logging [handler]
  (fn [request]
    (println (:request-method request) (:uri request))
    (handler request)))

(require '[ring.adapter.jetty :as jetty])
(def server (jetty/run-jetty (wrap-logging handler) {:port 3000 :join? false}))
;; (.stop server)

39.2 Reitit: Data-Driven Routing

(ns myapp.web
  (:require [reitit.ring :as ring]
            [reitit.ring.middleware.muuntaja :as muuntaja]
            [reitit.ring.middleware.parameters :as parameters]
            [reitit.ring.coercion :as coercion]
            [reitit.coercion.malli :as rcm]
            [muuntaja.core :as mc]
            [ring.adapter.jetty :as jetty]))

(def todos (atom {1 {:id 1 :title "Learn Clojure" :done false}}))

(def app
  (ring/ring-handler
    (ring/router
      [["/api"
        ["/ping" {:get (fn [_] {:status 200 :body {:message "pong"}})}]
        ["/todos" {:get (fn [_] {:status 200 :body (vals @todos)})
                   :post {:parameters {:body [:map [:title :string]]}
                          :handler (fn [{{{:keys [title]} :body} :parameters}]
                                     (let [id (inc (count @todos))
                                           todo {:id id :title title :done false}]
                                       (swap! todos assoc id todo)
                                       {:status 201 :body todo}))}}]
        ["/todos/:id" {:get {:parameters {:path [:map [:id :int]]}
                             :handler (fn [{{{:keys [id]} :path} :parameters}]
       
…

39.3 Ecosystem

HTTP abstraction + middleware Reitit / Compojure / Bidi

Jetty, http-kit, Aleph, Undertow (via ring-undertow)

Pedestal, Kit, Biff, Duct Frameworks / templates Muuntaja, jsonista Content negotiation, JSON Hiccup, Selmer

HTML generation (data → HTML), Django-like templates Authentication, authorization, crypto, JWT

clj-http, hato, http-kit client

(require '[hiccup2.core :as h])
(str (h/html [:div {:class "card"} [:h1 "Hello"] [:ul (for [x ["a" "b"]] [:li x])]]))
;; "<div class=\"card\"><h1>Hello</h1><ul><li>a</li><li>b</li></ul></div>"