branch: externals/plz commit a5f22b23e182cd9365a6ccefdcb96b0ca51df374 Author: Adam Porter <a...@alphapapa.net> Commit: Adam Porter <a...@alphapapa.net>
Add: (plz) Not sure which I like better, but this works. --- plz.el | 46 +++++++++++++++++++++++++++++++++++++++++++--- tests/test-plz.el | 33 +++++++++++++++++++++++++-------- 2 files changed, 68 insertions(+), 11 deletions(-) diff --git a/plz.el b/plz.el index e92742ba9d..551330343d 100644 --- a/plz.el +++ b/plz.el @@ -265,6 +265,45 @@ the initial connection attempt." :decode (if (and decode-s (not decode)) nil decode) :as as :then then :else else)) +(cl-defun plz (method url &key headers body as then else + (connect-timeout plz-connect-timeout) + (decode t decode-s)) + "Request BODY with METHOD to URL with curl. + +AS selects the kind of result to pass to the callback function +THEN. It may be: + +- `buffer' to pass the response buffer. +- `binary' to pass the response body as an undecoded string. +- `string' to pass the response body as a decoded string. +- `response' to pass a `plz-response' struct. +- A function, which is called in the response buffer with it + narrowed to the response body (suitable for, e.g. `json-read'). + +If DECODE is non-nil, the response body is decoded automatically. +For binary content, it should be nil. When AS is `binary', +DECODE is automatically set to nil. + +THEN is a callback function, whose sole argument is selected +above with AS. + +ELSE is an optional callback function called when the request +fails with one argument, a `plz-error' struct. If ELSE is nil, +an error is signaled when the request fails, either +`plz-curl-error' or `plz-http-error' as appropriate, with a +`plz-error' struct as the error data. + +HEADERS may be an alist of extra headers to send with the +request. CONNECT-TIMEOUT may be a number of seconds to timeout +the initial connection attempt." + (declare (indent defun)) + (plz--curl method url + :body body + :headers headers + :connect-timeout connect-timeout + :decode (if (and decode-s (not decode)) nil decode) + :as as :then then :else else)) + (cl-defun plz-get-sync (url &key headers as (connect-timeout plz-connect-timeout) (decode t decode-s)) @@ -338,9 +377,10 @@ the initial connection attempt." (curl-args (append plz-curl-default-args header-args (when connect-timeout (list "--connect-timeout" (number-to-string connect-timeout))) - (when (eq 'put method) - (cl-assert body) - (list "--data" "@-" "--request" "PUT")) + (pcase method + ((or 'put 'post) + (cl-assert body) + (list "--data" "@-" "--request" (upcase (symbol-name method))))) (list url))) (decode (pcase as ('binary nil) diff --git a/tests/test-plz.el b/tests/test-plz.el index 23ecefd7ff..cd055b4cc7 100644 --- a/tests/test-plz.el +++ b/tests/test-plz.el @@ -68,7 +68,7 @@ (ert-deftest plz-get-string nil (let* ((test-string) - (process (plz-get "https://httpbin.org/get" + (process (plz 'get "https://httpbin.org/get" :as 'string :then (lambda (string) (setf test-string string))))) @@ -78,7 +78,7 @@ (ert-deftest plz-get-buffer nil ;; The sentinel kills the buffer, so we get the buffer as a string. (let* ((test-buffer-string) - (process (plz-get "https://httpbin.org/get" + (process (plz 'get "https://httpbin.org/get" :as 'buffer :then (lambda (buffer) (with-current-buffer buffer @@ -88,7 +88,7 @@ (ert-deftest plz-get-response nil (let* ((test-response) - (process (plz-get "https://httpbin.org/get" + (process (plz 'get "https://httpbin.org/get" :as 'response :then (lambda (response) (setf test-response response))))) @@ -97,7 +97,7 @@ (ert-deftest plz-get-json nil (let* ((test-json) - (process (plz-get "https://httpbin.org/get" + (process (plz 'get "https://httpbin.org/get" :as #'json-read :then (lambda (json) (setf test-json json))))) @@ -105,11 +105,28 @@ (let-alist test-json (should (string-match "curl" .headers.User-Agent))))) +(ert-deftest plz-post-json-string nil + (let* ((json-string (json-encode (list (cons "key" "value")))) + (response-json) + (process (plz 'post "https://httpbin.org/post" + :headers '(("Content-Type" . "application/json")) + :body json-string + :as #'json-read + :then (lambda (json) + (setf response-json json))))) + (plz-test-wait process) + (let-alist response-json + (should (string-match "curl" .headers.User-Agent)) + (should (string= "value" (alist-get 'key (json-read-from-string .data))))))) + +;; TODO: POST JSON buffer. + (ert-deftest plz-put-json-string nil (let* ((json-string (json-encode (list (cons "key" "value")))) (response-json) - (process (plz-put "https://httpbin.org/put" json-string + (process (plz 'put "https://httpbin.org/put" :headers '(("Content-Type" . "application/json")) + :body json-string :as #'json-read :then (lambda (json) (setf response-json json))))) @@ -146,7 +163,7 @@ (ert-deftest plz-get-curl-error nil ;; Async. (let* ((err) - (process (plz-get "https://httpbinnnnnn.org/get/status/404" + (process (plz 'get "https://httpbinnnnnn.org/get/status/404" :as 'string :else (lambda (e) (setf err e))))) @@ -167,7 +184,7 @@ (ert-deftest plz-get-404-error nil ;; Async. (let* ((err) - (process (plz-get "https://httpbin.org/get/status/404" + (process (plz 'get "https://httpbin.org/get/status/404" :as 'string :else (lambda (e) (setf err e))))) @@ -189,7 +206,7 @@ (ert-deftest plz-get-jpeg () (let* ((test-jpeg) - (process (plz-get "https://httpbin.org/image/jpeg" + (process (plz 'get "https://httpbin.org/image/jpeg" :as 'binary :then (lambda (string) (setf test-jpeg string)))))