Next: Installation [Contents]
file:http://elpa.gnu.org/packages/plz.svg
plz
is an HTTP library for Emacs. It uses curl
as a backend, which avoids some of the issues with using Emacs’s built-in url
library. It supports both synchronous and asynchronous requests. Its API is intended to be simple, natural, and expressive. Its code is intended to be simple and well-organized. Every feature is tested against httpbin.
Next: Manual, Up: Installation [Contents]
plz
is available in GNU ELPA. It may be installed in Emacs using the package-install
command.
Previous: GNU ELPA, Up: Installation [Contents]
plz
has no dependencies other than Emacs and curl
. It’s known to work on Emacs 26.3 or later. To install it manually, simply place ‘plz.el’ in your load-path
and (require 'plz)
.
Next: Changelog, Previous: Installation, Up: plz.el [Contents]
The main public function is plz
, which sends an HTTP request and returns either the result of the specified type (for a synchronous request), or the curl
process object (for asynchronous requests). For asynchronous requests, callback, error-handling, and finalizer functions may be specified, as well as various other options.
Synchronously ‘GET’ a URL and return the response body as a decoded string (here, raw JSON):
(plz 'get "https://httpbin.org/user-agent")
"{\n \"user-agent\": \"curl/7.35.0\"\n}\n"
Synchronously ‘GET’ a URL that returns a JSON object, and parse and return it as an alist:
(plz 'get "https://httpbin.org/get" :as #'json-read)
((args) (headers (Accept . "*/*") (Accept-Encoding . "deflate, gzip") (Host . "httpbin.org") (User-Agent . "curl/7.35.0")) (url . "https://httpbin.org/get"))
Asynchronously ‘POST’ a JSON object in the request body, then parse a JSON object from the response body, and call a function with the result:
(plz 'post "https://httpbin.org/post" :headers '(("Content-Type" . "application/json")) :body (json-encode '(("key" . "value"))) :as #'json-read :then (lambda (alist) (message "Result: %s" (alist-get 'data alist))))
Result: {"key":"value"}
Synchronously download a JPEG file, then create an Emacs image object from the data:
(let ((jpeg-data (plz 'get "https://httpbin.org/image/jpeg" :as 'binary))) (create-image jpeg-data nil 'data))
(image :type jpeg :data ""ÿØÿà^@^PJFIF...")
plz
(method url &key headers body else finally noquery (as ’string) (then ’sync) (body-type ’text) (decode t decode-s) (connect-timeout plz-connect-timeout) (timeout plz-timeout))
Request METHOD
from URL
with curl. Return the curl process object or, for a synchronous request, the selected result.
HEADERS
may be an alist of extra headers to send with the request.
BODY
may be a string, a buffer, or a list like (file FILENAME)
to upload a file from disk.
BODY-TYPE
may be text
to send BODY
as text, or binary
to send it as binary.
AS
selects the kind of result to pass to the callback function THEN
, or the kind of result to return for synchronous requests. It may be:
buffer
to pass the response buffer, which will be narrowed to the response body and decoded according to DECODE
.
binary
to pass the response body as an un-decoded string.
string
to pass the response body as a decoded string.
response
to pass a plz-response
structure.
file
to pass a temporary filename to which the response body has been saved without decoding.
(file ~FILENAME)
to pass FILENAME
after having saved the response body to it without decoding. FILENAME
must be a non-existent file; if it exists, it will not be overwritten, and an error will be signaled. FILENAME
is passed through expand-file-name
, which see.
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
; if the request fails and no ELSE
function is given (see below), the argument will be a plz-error
structure describing the error. Or THEN
may be sync
to make a synchronous request, in which case the result is returned directly from this function.
ELSE
is an optional callback function called when the request fails (i.e. if curl fails, or if the HTTP
response has a non-2xx status code). It is called with one argument, a plz-error
structure. If ELSE
is nil, a plz-curl-error
or plz-http-error
is signaled when the request fails, with a plz-error
structure as the error data. For synchronous requests, this argument is ignored.
NOTE
: In v0.8 of plz
, only one error will be signaled: plz-error
. The existing errors, plz-curl-error
and plz-http-error
, inherit from plz-error
to allow applications to update their code while using v0.7 (i.e. any condition-case
forms should now handle only plz-error
, not the other two).
FINALLY
is an optional function called without argument after THEN
or ELSE
, as appropriate. For synchronous requests, this argument is ignored.
CONNECT-TIMEOUT
and TIMEOUT
are a number of seconds that limit how long it takes to connect to a host and to receive a response from a host, respectively.
NOQUERY
is passed to make-process
, which see.
FILTER
is an optional function to be used as the process filter for the curl process. It can be used to handle HTTP responses in a streaming way. The function must accept 2 arguments, the process object running curl, and a string which is output received from the process. The default process filter inserts the output of the process into the process buffer. The provided FILTER
function should at least insert output up to the HTTP body into the process buffer.
plz
provides a simple system for queueing HTTP requests. First, make a plz-queue
struct by calling make-plz-queue
. Then call plz-queue
with the struct as the first argument, and the rest of the arguments being the same as those passed to plz
. Then call plz-run
to run the queued requests.
All of the queue-related functions return the queue as their value, making them easy to use. For example:
(defvar my-queue (make-plz-queue :limit 2)) (plz-run (plz-queue my-queue 'get "https://httpbin.org/get?foo=0" :then (lambda (body) (message "%s" body))))
Or:
(let ((queue (make-plz-queue :limit 2 :finally (lambda () (message "Queue empty.")))) (urls '("https://httpbin.org/get?foo=0" "https://httpbin.org/get?foo=1"))) (plz-run (dolist (url urls queue) (plz-queue queue 'get url :then (lambda (body) (message "%s" body))))))
You may also clear a queue with plz-clear
, which cancels any active or queued requests and calls their :else
functions. And plz-length
returns the number of a queue’s active and queued requests.
Fixes
Compatibility
plz
with Emacs versions older than 27.1. For Emacs 26.3, an earlier version of plz
may be used, or this version might be compatible, with or without minor changes, which the maintainer cannot offer support for.)
Changes
plz-timeout
is removed. (It was the default value for plz
’s :timeout
argument, which is passed to Curl as its --max-time
argument, limiting the total duration of a request operation. This argument should be unset by default, because larger or slower downloads might not finish within a certain duration, and it is surprising to the user to have this option set by default, potentially causing requests to timeout unnecessarily.)
:as 'file
or :as '(file FILENAME)
now passes the filename to Curl, allowing it to write the data to the file itself (rather than receiving the data into an Emacs buffer and then writing it to a file. This improves performance when downloading large files, significantly reducing Emacs’s CPU and memory usage).
Fixes
plz
has returned for a synchronous request. See #53. Thanks to Joseph Turner for extensive help debugging, and to USHIN for sponsoring some of this work.)
generate-new-buffer
(as extra protection against "kill buffer?" prompts in case of errors). (See #52. Thanks to Michał Krzywkowski.)
Development
plz
is now automatically tested against Emacs versions 27.1, 27.2, 28.1, 28.2, 29.1, 29.2, 29.3, and a recent snapshot of the master
branch (adding 29.2 and 29.3).
Additions
plz
now accepts a :filter
argument which can be used to override the default process filter (e.g. for streaming responses). (#43, #50. Thanks to Roman Scherer.)
Fixes
Fixes
Changes
plz-error
, is defined. The existing signals, plz-curl-error
and plz-http-error
, inherit from it, so handling plz-error
catches both.
NOTE: The existing signals, plz-curl-error
and plz-http-error
, are hereby deprecated, and they will be removed in v0.8. Applications should be updated while using v0.7 to only expect plz-error
.
Fixes
with-local-quit
for synchronous requests (preventing Emacs from complaining sometimes). (Fixes #26.)
:as 'buffer
result type: decode body when appropriate; unset multibyte for binary; narrow to body; don’t kill buffer prematurely.
Internal
httpbin.org
server is often overloaded).
Additions
plz
’s :body
argument now accepts a list like (file FILENAME)
to upload a file from disk (by passing the filename to curl, rather than reading its content into Emacs and sending it to curl through the pipe).
Fixes
plz
’s docstring now mentions that the :body
argument may also be a buffer (an intentional feature that was accidentally undocumented).
:as 'response
.
Fixes
finally
function after queue is empty. (New features should not be designed and released on a Friday.)
Fixes
plz-queue
struct to end to prevent invalid byte-compiler expansions for already-compiled applications (which would require them to be recompiled after upgrading plz
).
Fixes
plz-queue
’s finally
function when specified.
Fixes
plz-queue
’s finally
function when specified. (Thanks to Dan Oriani for reporting.)
Additions
plz-queue
’s finally
slot, a function called when the queue is finished.
Additions
HEAD
requests. (Thanks to USHIN for sponsoring.)
Changes
POST
and PUT
requests without bodies. (#16. Thanks to Joseph Turner for reporting. Thanks to USHIN for sponsoring.)
Fixes
Internal
Additions
Fixes
checkdoc
linting succeeds).
Fixes
Next: Development, Previous: Changelog, Up: plz.el [Contents]
Bug reports, feature requests, suggestions — oh my!
Note that plz
is a young library, and its only client so far is Ement.el. There are a variety of HTTP and curl
features it does not yet support, since they have not been needed by the author. Patches are welcome, as long as they include passing tests.
Up: Development [Contents]
This package is part of GNU Emacs, being distributed in GNU ELPA. Contributions to this project must follow GNU guidelines, which means that, as with other parts of Emacs, patches of more than a few lines must be accompanied by having assigned copyright for the contribution to the FSF. Contributors who wish to do so may contact emacs-devel@gnu.org to request the assignment form.