fukamachi / ningle

Super micro framework for Common Lisp
http://8arrow.org/ningle/
273 stars 25 forks source link

ningle middlewares and exposing lack's environment #41

Closed dnaeon closed 1 year ago

dnaeon commented 1 year ago

Hey there,

In a way this one is related to https://github.com/fukamachi/ningle/issues/6 , where additional metadata can be passed as part of the context.

Currently in ningle it is possible to wrap an application using lack:builder and in turn embed additional middleware-specific data to the environment, but this data is not exposed to controllers.

For example.

(ql:quickload :ningle)
(ql:quickload :lack)
(ql:quickload :clack)

(defun my-custom-middleware ()
  (lambda (app)
    (lambda (env)
      (setf (getf env :my-custom-middleware/some-data) "Here goes my data")
      (funcall app env))))

(defparameter *app* (make-instance 'ningle:app))

(setf (ningle:route *app* "/")
      (lambda (params)
        (declare (ignore params))
        "Welcome to ningle!"))

(defparameter *wrapped-app* (lack:builder (my-custom-middleware) *app*))
(defparameter *server* (clack:clackup *wrapped-app*))

While this is valid and :my-custom-middleware/some-data ends up in the environment, this environment is never passed or exposed to controllers while ningle dispatches them, as a controller receives a single argument only, which is params.

On the other hand what is available to controllers as additional data is based on the context, but that context contains pre-defined list of keys to be passed down.

@export
(defun make-context (app env)
  "Create a new Context."
  (let ((*context* (make-hash-table)))
    (setf (context :request) (make-request app env)
          (context :response) (make-response app 200 ())
          (context :session) (getf env :lack.session))
    *context*))

Is there any way the env can be passed to controllers as well, similar to what Clack does, which would enable custom middlewares to be implemented as well?

Thanks!

dnaeon commented 1 year ago

I've managed to workaround this by creating a custom app based on ningle:app, but I think ideally this should be supported in ningle itself.

https://gist.github.com/dnaeon/3a3f86dea1096db5a9231d1f56a565e2

dnaeon commented 1 year ago

Just realized that I could use lack.request:request-env with ningle:*request* to get the environment. I guess that was not very clear to me as a first time user of lack/clack/ningle.