Web Development

46.1 Hunchentoot (Web Server)

REPL-driven web development: redefine a handler, and the next request uses the new code immediately.

(ql:quickload '("hunchentoot" "spinneret" "com.inuoe.jzon"))

(defvar *server* (make-instance 'hunchentoot:easy-acceptor :port 4242))

(hunchentoot:define-easy-handler (home :uri "/") ()
  (setf (hunchentoot:content-type*) "text/html")
  (spinneret:with-html-string
    (:html
     (:head (:title "Lisp Web"))
     (:body (:h1 "Hello from Common Lisp")
            (:p "Served by Hunchentoot")))))

(hunchentoot:define-easy-handler (hello :uri "/hello") (name)   ; query/form parameter ?name=...
  (setf (hunchentoot:content-type*) "text/plain")
  (format nil "Hello, ~a!" (or name "world")))

(hunchentoot:define-easy-handler (api-items :uri "/api/items") ()
  (setf (hunchentoot:content-type*) "application/json")
  (com.inuoe.jzon:stringify #(1 2 3)))

(hunchentoot:start *server*)                          ; visit http://localhost:4242/
;; (hunchentoot:stop *server*)

46.2 Clack/Lack, Ningle and Caveman

Web application environment and middleware (like Rack/WSGI) Mature, standalone web server High-performance server (libev)

Caveman2, Ningle, Snooze, Radiance Frameworks / routing Spinneret, cl-who, Djula HTML generation / templates

Build web/desktop GUIs from Lisp over WebSockets Dexador, Drakma websocket-driver, hunchensocket cl-jwt, cl-bcrypt/ironclad Auth and crypto

(ql:quickload '("clack" "ningle"))
(defvar *app* (make-instance 'ningle:app))
(setf (ningle:route *app* "/") "Welcome to ningle!")
(setf (ningle:route *app* "/users/:id")
      (lambda (params) (format nil "User ~a" (cdr (assoc :id params)))))
(clack:clackup *app* :server :woo :port 5000)        ; Woo: a very fast libev-based server
;; HTTP client
(ql:quickload "dexador")
(dex:get "https://api.github.com/repos/sbcl/sbcl")    ; body, status, headers, uri, stream
(dex:post "https://httpbin.org/post" :content "{\"a\":1}" :headers '(("Content-Type" . "application/json")))