Yesterday, I’ve showed you how does Clack work. A web app is a function which returns a list with the response or a function which should return create such list pass it to the provided callback.
Now we’ll add a logging to our app with the lack-middleware-accesslog
system.
To do this, we must wrap our app’s function into another function like this:
;; Now we'll create a simple app:
POFTHEDAY> (defparameter *app*
(lambda (env)
'(200 (:content-type "text/plain")
("Hello, World"))))
;; And wrap it into the middleware:
POFTHEDAY> (defparameter *app-with-access-log*
(funcall lack.middleware.accesslog:*lack-middleware-accesslog*
*app*))
;; Now it's time to start our app:
POFTHEDAY> (clack:clackup *app-with-access-log*
:port 8000)
Woo server is started.
Listening on 127.0.0.1:8000.
;; And to make a test request:
POFTHEDAY> (values (dex:get "http://localhost:8000/"))
127.0.0.1 - [21/Jun/2020:22:50:52 +03:00] "GET / HTTP/1.1"
200 12 "-" "Dexador/0.9.14 (SBCL 2.0.2); Darwin; 19.5.0"
"Hello, World"
Look how a log message was printed to the STDOUT.
Now let’s see how does this middleware works. Here is its content. It is a little bit complicated because the middleware needs to handle cases when an app returns a function instead of the normal response:
(defparameter *lack-middleware-accesslog*
(let ((no-body '#:no-body))
(lambda (app &key
(logger
(lambda (output) (format t "~&~A~%" output)))
(formatter #'default-formatter))
(lambda (env)
(funcall-with-cb
app env
(lambda (res)
(funcall logger
(funcall formatter env res (now)))
res)))))
"Middleware for logging requests")
I’ll show you a simpler version of this logging middleware:
;; Here is the middleware:
POFTHEDAY> (defun simple-logging (app)
(lambda (env)
(let ((response
(funcall app env)))
(format t "~A ~A -> ~A~%"
(getf env :request-method)
(getf env :path-info)
(car response))
response)))
;; And this is an example how we can apply it to our app:
POFTHEDAY> (defparameter *app-with-simple-log*
(simple-logging *app*))
POFTHEDAY> (clack:clackup *app-with-simple-log*
:port 8000)
Hunchentoot server is started.
Listening on 127.0.0.1:8000.
POFTHEDAY> (values (dex:get "http://localhost:8000/"))
GET / -> 200
"Hello, World"
POFTHEDAY> (values (dex:get "http://localhost:8000/foo/bar"))
GET /foo/bar -> 200
"Hello, World"
Tomorrow we’ll try the better way to apply middlewares to a Clack app.