2014-04-07 7 views
8

Ich finde, dass die inkrementelle Entwicklung beim Codieren von Hunchentoot tendenziell abbricht.Zugreifen auf Hunchentoot-Request-Objekte von der REPL zum Debuggen

Zum Beispiel könnte ich eine Webseite schreiben, die aus ein paar Funktionen besteht. Wenn eine dieser inneren Funktionen einen Aufruf an - sagen wir - hunchentoot: post-parameters * enthält, kann ich die Funktion in der REPL nicht einfach testen. Es tritt ein Fehler auf, weil * Anfrage * nicht existiert, es sei denn, die Seite wird von einem Web-Client aufgerufen.

Es wäre schön, wenn einige funktions oder-andere-Quelle so bestand, dass ich so meine-Funktion testen konnte:

>(let* ((*request* (get-previous-request-from-somewhere)) 
     (*session* (slot-value *request* 'hunchentoot:session))) 
    (my-function <whatever params>)) 

Tut es oder etwas ähnliches gibt es? Habe ich einen besseren Ansatz zum Debuggen übersehen?

+0

Es scheint, dass Sie nur ein Gerät erstellen müssen, das eine Scheinanforderung zurückgibt. Das sollte nicht sehr schwer sein. Zum Beispiel siehe: https://github.com/russell/planet-git/blob/master/t/traverser.lisp#L55-L63 Fiveam hat Leuchten, wenn Sie so geneigt sind – PuercoPop

Antwort

6

Meine Zwischenlösung sieht ungefähr so ​​aus:

(defparameter *save-last-request* t) 
(defvar *last-request* nil) 

(defun store-request() 
    (when *save-last-request* 
    (setf *last-request* *request*))) 

(defmacro with-last-request (&body body) 
    `(let* ((*request* *last-request*) 
     (*session* (slot-value *request* 'hunchentoot:session))) 
    ,@body)) 

Es funktioniert gut, mit dem Vorbehalt, dass jeder Handler einen Aufruf an store-request machen muss.

+0

Da dies mindestens eine halbe Klamm ist (da Store-Request explizit aufgerufen werden muss), habe ich Zweifel, ob das ganze Bounty gewährt werden soll - wenn jemand so freundlich wäre, einen weiteren +1 zu geben, würde automatisch die Hälfte des Bountys gewährt - also bitte abstimmen: -) –

1

Ich denke, die einfachste Sache zu tun wäre, eine benutzerdefinierte Anfrage Klasse zu verwenden, die eine Möglichkeit bietet, Anforderungen irgendwo in der Initialisierungskette zu persistieren.

Hier ist ein triviales Beispiel für einen Ansatz. Eine benutzerdefinierte Unterklasse der Anfrage, die ihren Status in einem globalen Stapel speichert.

Sie können Ihre Akzeptoren zu verwenden, um benutzerdefinierte Anfrage-Klassen

(setf (acceptor-request-class acceptor) new-value)

so etwas wie dieses

(defparameter *requests* nil) 
(defclass my-request (hunchentoot:request)()) 
(defmethod initialize-instance :after ((req my-request) &key) 
    (push req *requests*)) 

gesetzt und dann die Akzeptor-Anfrage Klasse, diese zu verwenden, wenn Sie Ihre machen Akzeptor z

(setf (hunchentoot:acceptor-request-class 
     (make-instance 'hunchentoot:easy-acceptor)) 'my-request) 

Jedes Mal, wenn eine Anforderung von diesem Akzeptor erstellt wird an die Prozedur zu übergeben, wird es in die *requests* Liste hinzugefügt werden.

Wenn Sie eine Variable zum Angeben des Namens der Anforderungsklasse verwenden, können Sie diese Klasse für Entwicklung/Debugging ein- und ausschalten.

Sie könnten dann Anfragen von diesem Stapel in Ihrer Testbindung übernehmen.

Verwandte Themen