2017-02-28 2 views
0

Ich bin relativ neu zu Common Lisp (SBCL) und Hunchentoot (mit Quicklisp). Kann mir jemand sagen, wie ich das zur Arbeit bringen kann? Ich versuche, einen Hunchentoot-Server und einige Pfade in einer Funktion als Einheit zu verpacken. Wenn ich dies ausführe, ist nur die Indexseite von Hunchentoot verfügbar, die Pfade/a und/b nicht.Hunchentoot Dispatcher

(defun app0 (port) 
    (let ((*dispatch-table* nil) (server (make-instance 'hunchentoot:acceptor :port port))) 
    (push (hunchentoot:create-prefix-dispatcher "/a" (lambda() "a")) *dispatch-table*) 
    (push (hunchentoot:create-prefix-dispatcher "/b" (lambda() "b")) *dispatch-table*) 
    (hunchentoot:start server) server)) 
+0

'* Dispatch-Tabelle *' ist bereits eine globale Variable. –

Antwort

3

Es gibt mehrere Probleme, soweit ich sehen kann. Zunächst wird die Anforderungsverarbeitung über *dispatch-table* erfordert, dass der Akzeptor vom Typ easy-acceptor, das heißt, Sie müssen

(make-instance 'easy-acceptor ...) 

Die documentation die Details hat.

Das zweite Problem ist, dass Sie die *dispatch-table* während des Setup-Codes erneut binden und neue Werte in diese Bindung schieben. Da die Bindung zurückgesetzt wird, nachdem die let beendet ist (und hunchentoot:start asynchron funktioniert), sind Ihre Einträge in der *dispatch-table* effektiv verloren, wenn der Server ausgeführt wird. Versuchen Sie

(push (hunchentoot:create-prefix-dispatcher "/a" (lambda() "a")) *dispatch-table*) 
(push (hunchentoot:create-prefix-dispatcher "/b" (lambda() "b")) *dispatch-table*) 

auf der obersten Ebene (oder machen Sie so etwas in einer dedizierten Setup-Funktion). Wenn Sie den globalen Ansatz *dispatch-table* nicht mögen, können Sie auch eine Unterklasse von acceptor erstellen und acceptor-dispatch-request überschreiben (und damit jede beliebige Art von Versand implementieren).

Nur als Randnotiz: Sie nicht Präfix *dispatch-table*, während Sie praktisch jedes andere Symbol aus hunchentoot Paket vorangestellt. Ist das nur ein Fehler beim Kopieren/Einfügen, oder ist das auch in Ihrem tatsächlichen Code der Fall? Wenn Sie das :use Paket hunchentoot nicht in dem Paket enthalten, in dem Ihr Code gespeichert ist, müssen Sie auch die Versandtabelle als hunchentoot:*dispatch-table* qualifizieren.

bearbeiten (die Frage im Kommentarbereich zu adressieren) Es gibt eine example in the hunchentoot documentation, die genau das zu tun scheint, was Sie tun möchten:

(defclass vhost (tbnl:acceptor) 
    ((dispatch-table 
    :initform '() 
    :accessor dispatch-table 
    :documentation "List of dispatch functions")) 
    (:default-initargs 
    :address "127.0.0.1")) 

(defmethod tbnl:acceptor-dispatch-request ((vhost vhost) request) 
    (mapc (lambda (dispatcher) 
     (let ((handler (funcall dispatcher request))) 
     (when handler 
      (return-from tbnl:acceptor-dispatch-request (funcall handler))))) 
    (dispatch-table vhost)) 
    (call-next-method)) 

(defvar vhost1 (make-instance 'vhost :port 50001)) 
(defvar vhost2 (make-instance 'vhost :port 50002)) 

(push 
(tbnl:create-prefix-dispatcher "/foo" 'foo1) 
(dispatch-table vhost1)) 
(push 
(tbnl:create-prefix-dispatcher "/foo" 'foo2) 
(dispatch-table vhost2)) 

(defun foo1() "Hello") 
(defun foo2() "Goodbye") 

(tbnl:start vhost1) 
(tbnl:start vhost2) 

(Kommentare in der Dokumentation der Kürze entfernt) . Die tbnl ist ein vordefinierter Kurzname für das Paket hunchentoot. Sie können beide austauschbar verwenden, obwohl ich empfehlen würde, dass Sie einen auswählen und dabei bleiben. Das Mischen von beiden könnte zu Verwirrung führen.

+0

Danke für Ihre Antwort. Das erste/Problem war ein Tippfehler in meinem Code, und ich habe es auf easy-acceptor gesetzt, ich werde meinen Beitrag in Kürze aktualisieren. Der zweite Teil hilft wirklich, einige Verwirrung zu beseitigen, die ich um Bindungen und hunchentoot hatte, diese Wege nicht zu sehen. Ich konnte nicht erkennen, dass die Bindungen zurückgesetzt wurden. Auch danke für die Randnotiz, leider habe ich keine * Versand-Tabelle * mit dem Paketnamen vorangestellt. – rebnoob

+0

Ich bin nicht wirklich auf der Suche nach ausgefallenen Dispatching, also würde ich gerne Subclassing Akzeptor vermeiden und dabei Fehler einführen. Was ich damit erreichen wollte, war, mehrere Instanzen eines Servers erstellen zu können, der auf verschiedenen Ports mit einigen instanzspezifischen Daten wie einer db-Verbindung läuft. Würden Sie den besten Weg empfehlen, das zu tun? – rebnoob

+0

Das klappt, danke Dirk! – rebnoob