Choose at runtime how to respond to a request

(= baseops* (table))

(extend respond (req) (baseops* req!op)
  (it req))

; TODO using one of srv's defop etc. should wipe name in baseops*

(mac defop-base (name . body)
  (w/uniq request
    `(do (wipe (srvops* ',name)
               (redirector* ',name))
         (= (baseops* ',name)
            (fn (,request)
              (w/req ,request ,@body))))))

(def cook (k v (o persistent))
  (push (list k v persistent) req!cookies-to-set))

(def rmcook (k)
  (push k req!cookies-to-remove))

(def pr-cookies ()
  (each cook req!cookies-to-set
    (whenlet (k v (o persistent)) cook
      (pr "Set-Cookie: " k "=" v)
      (when persistent
        (pr "; expires=Sun, 17-Jan-2038 19:14:07 GMT"))
  (each k req!cookies-to-remove
    (prn "Set-Cookie: " k "=; expires=Thu, 01 Jan 1970 00:00:00 GMT")))

(def html-content ()
  (prn header*)

(def redirect (url)
  (prn rdheader*)
  (prn "Location: " url)

(= bfnurl* "/b")

(defop-base b
  (aif (fns* (sym (arg "fnid")))
        (redirect "deadlink")))

(mac baform (f . body)
  `(tag (form method 'post action bfnurl*)
     (fnid-field (fnid ,f))

(def bflink (f)
  (string bfnurl* "?fnid=" (fnid f)))

(mac w/blink (expr . body)
  `(tag (a href (bflink (fn () ,expr)))

(mac onblink (text . body)
  `(w/blink (do ,@body) (pr ,text)))


Arc’s srv defines

defopoutputs a text/html content type
defop-rawoutputs a text/html content type, and allows additional headers to be added
defoproutputs a redirect
defopr-rawoutputs a redirect, and allows additional headers to be added

with associated derived definitions such as w/link, w/rlink, aform, arform, and so on.

This hack defines a defop-base which outputs no headers at all. The op can then choose whether to output an HTML page or a redirect, or to issue a redirect while also setting a cookie, etc.

(defop-base show
  (if (authorized)
    (do (html-content)
        (whitepage (pr "The secret is: foo")))
    (do (cook "login-return" "show")
        (redirect "/login"))))

The request object is passed implicitly in a base op, which avoids having to pass req through to the utility functions like html-content, cook, and redirect.


This hack depends on arc3.1, extend0, implicitreq0, and srv-misc1.

Get this hack

Using the hackinator:

$ hack \ \ \ \ \ \ \ \ \ \ \


Same as Arc.

Contact me

Twitter: awwx
Email: andrew.wilcox [at]