EQL5/examples/X-extras/server-request.lisp

50 lines
1.9 KiB
Common Lisp

;;; this is just a snippet to show how to use Qt for POST requests to
;;; a cgi script (using e.g. python for cgi)
;;;
;;; this is here to have an alternative to Lisp solutions, which don't
;;; work well in ECL on some platforms (namely Windows)
;;;
;;; example usage:
;;;
;;; (server-request "booking.py"
;;; (list (cons "from" "2020-08-01")
;;; (cons "to "2020-08-08")))
(qrequire :network)
;; for testing, using e.g. python3 -m http.server 8080 --cgi
(defparameter *server* "http://localhost:8080/cgi-bin/")
(defun http-part (parameter)
(let ((part (qnew "QHttpPart")))
(qlet ((name "QVariant(QString)"
(format nil "form-data; name=~S" (car parameter))))
(|setHeader| part |QNetworkRequest.ContentDispositionHeader| name)
(|setBody| part (x:string-to-bytes (cdr parameter))))
part))
(defun server-request (script &optional parameters)
"Make a http POST request to a cgi script, forcing synchronous behaviour,
which simplifies things and is preferable in many cases."
(start-busy-animation) ; pseudo code
(let (response)
(qlet ((ev-loop "QEventLoop")
(manager "QNetworkAccessManager"))
(qconnect manager "finished(QNetworkReply*)"
(lambda (reply)
(|deleteLater| reply)
(let ((err (|error| reply)))
(when (= |QNetworkReply.NoError| err)
(setf response (qfrom-utf8 (|readAll| reply)))))
(|exit| ev-loop)))
(qlet ((multi "QHttpMultiPart")
(qurl "QUrl(QString)" (x:cc *server* script))
(request "QNetworkRequest(QUrl)" qurl))
(dolist (param parameters)
(qlet ((part (http-part param)))
(|append| multi part)))
(|post| manager request multi)
(|exec| ev-loop |QEventLoop.ExcludeUserInputEvents|)
(stop-busy-animation) ; pseudo code
response))))