Skip to content

Latest commit

 

History

History
123 lines (102 loc) · 3.51 KB

0117-clack-pretend.org

File metadata and controls

123 lines (102 loc) · 3.51 KB

clack-pretend

This is the last middleware in our Clack/Lack series. What does it do? It helps during website development remembering last requests you did from the browser and allowing to replay them from the REPL.

Clack-pretend interposes itself into a Lack middlewares chain. To define the app you need to use a special builder macro and to specify at which point requests and responses should be captured:

POFTHEDAY> (defparameter *app*
             (clack-pretend:pretend-builder (:insert 2)
               :accesslog
               :session
               (lambda (env)
                 (let* ((path (getf env :path-info))
                        (query (getf env :query-string))
                        (message (format nil "Path: ~A, query: ~A"
                                         path query)))
                   (format t "Processing request:~%  ~A~%"
                           message)
                   '(200 (:content-type "text/plain")
                     ("Hello world!"))))))
*APP*
POFTHEDAY> (defparameter *server*
             (clack:clackup *app*
                            :port 8000))
Hunchentoot server is started.
Listening on 127.0.0.1:8000.

Now I’ll make a request using curl:

[poftheday] curl -v 'http://localhost:8000/some/route?foo=Bar'
> GET /some/route?foo=Bar HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Wed, 01 Jul 2020 19:23:12 GMT
< Server: Hunchentoot 1.2.38
< Transfer-Encoding: chunked
< Content-Type: text/plain
< Set-Cookie: lack.session=0d629e3a1d2681d99c40f7b2086ec97d53e2b884; path=/; expires=Sat, 31 Dec 2140 14:45:27 GMT

And we can look up what was the last request:

POFTHEDAY> (clack-pretend:last-input)
(:LACK.SESSION.OPTIONS
 (:ID "0d629e3a1d2681d99c40f7b2086ec97d53e2b884"
  :NEW-SESSION T :CHANGE-ID NIL :EXPIRE NIL)
 :LACK.SESSION #<HASH-TABLE :TEST EQUAL :COUNT 0 {1005EB8A03}>
 :REQUEST-METHOD :GET
 :SCRIPT-NAME ""
 :PATH-INFO "/some/route"
 :SERVER-NAME "localhost"
 :SERVER-PORT 8000
 :SERVER-PROTOCOL :HTTP/1.1
 :REQUEST-URI "/some/route?foo=Bar"
 :URL-SCHEME "http"
 :REMOTE-ADDR "127.0.0.1"
 :REMOTE-PORT 53671
 :QUERY-STRING "foo=Bar"
 :RAW-BODY #<FLEXI-STREAMS:FLEXI-IO-STREAM {1005EB6FD3}>
 :CONTENT-LENGTH NIL
 :CONTENT-TYPE NIL
 :CLACK.STREAMING T
 :CLACK.IO #<CLACK.HANDLER.HUNCHENTOOT::CLIENT {1005EB7043}>
 :HEADERS #<HASH-TABLE :TEST EQUAL :COUNT 3 {1005EB72C3}>
 :QUERY-PARAMETERS (("foo" . "Bar")))

POFTHEDAY> (rutils:hash-table-to-alist
            (getf * :headers))
(("host" . "localhost:8000")
 ("user-agent" . "curl/7.54.0")
 ("accept" . "*/*"))

Now it is time to replay the request from the REPL:

POFTHEDAY> (clack-pretend:run-pretend)
Processing request:
  Path: /some/route, query: foo=Bar
(200 (:CONTENT-TYPE "text/plain") ("Hello world!"))

;; You can override path to check, it with the same
;; headers and session:
POFTHEDAY> (clack-pretend:run-pretend
            :path-info "/other/path")
Processing request:
  Path: /other/path, query: foo=Bar
(200 (:CONTENT-TYPE "text/plain") ("Hello world!"))

Seems, clack-pretend is a great addition for web development with Clack.

It will be interesting to improve it to store not only the last N successful requests but also to store requests resulting unhandled error. This way you’ll be able to replay errors your users experience in production!