Quoth Hans Hübner hans.huebner@gmail.com:
On Thu, Sep 22, 2011 at 10:03 PM, Sebastian Tennant sebyte@smolny.plus.com wrote:
Quoth Hans Hübner hans.huebner@gmail.com:
IMHO, the fact that there's only a single *dispatch-table* is 'the big thing' that needs changing.
Adding a dispatch-table slot (with default value *dispatch-table*) to the acceptor class would probably suffice, though it's probably not that simple.
I can agree to that, but subclassing acceptors is not really modular (i.e. it is as right or wrong as the easy-acceptor subclass).
I was talking about adding a dispatch-table slot to the existing acceptor class. I was not talking about subclassing. My understanding of object oriented programming paradigms is limited so I can't say I fully understand why subclassing is 'not really modular', however simply adding a dispatch-table slot to the acceptor class would circumvent that problem.
I think it would make sense to have a dispatcher class. Every acceptor would have a dispatchers slot that contained a list of dispatcher instances which would be consulted, one after another, to route the request.
I'm sure this could be made to work well but it undoubtedly adds another layer of complexity.
I drew this visual model for myself when I was learning about hunchentoot:
+--------------------------+ +-----------<| Client |<---------------+ | +--------------------------+ | HTTP request HTML | | +---------------------------------------------------+ | | | req. obj. | | ACCEPTOR | PROCESS-REQUEST -------------> request dispatcher | ===> request handler +---------------------------------------------------+ | ^ | ^ req.| | req.| | obj.| NIL obj.| request handler | | | | *DISPATCH-TABLE* (dispatch function#1 dispatch function#2 ... dispatch function#N)
It would help me a lot if you could draw a similar model which incorporates dispatch tables and dispatch functions, as well as your proposed dispatcher object.
That way, it would be possible to share dispatcher instances between acceptors. For example, a web site could have a dispatcher for the anonymous, sessionless front-end functionality that would be used by the http port. The same dispatcher instance would be on the dispatchers list of the https acceptor, and in addition there would be a dispatcher instance for the, say, content management system on that acceptors dispatchers list.
Sharing dispatcher instances sounds good in theory but I'm not sure how useful it would be in practice (based on my own experience).
Also, the dispatcher class would be responsible for implementing virtual hosts, i.e. there would be one dispatcher for every virtual host supported.
Each virtual host already has its own acceptor so why does each virtual host need its own dispatcher object as well?
Now this sounds nice and easy,
Does it? :)
but it adds to the number of instances that need to be created in order to start Hunchentoot. Starting Hunchentoot in any but the most basic standard configurations is already a chore, requiring various make-instance invocations and initargs. If we move forward in this direction, I think we need to improve how Hunchentoot is configured and started, too. Basically, this would be a declarative syntax that contained the various classes and instantiation arguments.
It seems to me the solution is becoming more complicated than the problem we are trying to solve, namely improved support for virtual hosts.
My solution is simple, and backwards compatible:
(defun list-request-dispatcher (request) (let ((dispatch-table (if (fboundp 'acceptor-dispatch-table)) (eval (acceptor-dispatch-table *acceptor*)) *dispatch-table*))) (loop for dispatcher in dispatch-table for action = (funcall dispatcher request) when action return (funcall action) finally (setf (return-code *reply*) +http-not-found+)))))
where acceptor-dispatch-table is a reader method defined on an additional slot to the acceptor class; dispatch-table, with default value '*dispatch-table*.
"on github" means "in any fork", "the main repository" means edicl/hunchentoot.
OK, I see.
Yes. As soon as the freeze point is reached, that will happen. Before that, here is what I'd like to do:
- Conceptionalize dispatching [...]
- Implement declarative configuration
This seems to me like a lot of work and it also seems quite likely that you will have to do most (if not all) of it. And will these changes be backwards compatible? I suugest these be deferred to a subsequent release, one with a more significant version number bump; 1.2.0 say?
- Integrate Hunchensocket
I hadn't heard of hunchensocket until now, but I've no doubt it should be integrated. How easy or hard do you think this will be?
- Set up default file system with documentation and nice-looking error pages
I'm not sure what you mean by a default file system. Do you mean a dispatch function which matches a unique path:
/hunchendocs/manual.html
for example, which is added to *dispatch-table* by default?
As for 'nice-looking' error pages, don't forget that one person's nice is another person's ugly.
Sebastian