alphapapa / plz.el

An HTTP library for Emacs
GNU General Public License v3.0
192 stars 9 forks source link
curl emacs http

+TITLE: plz.el

+PROPERTY: LOGGING nil

NOTE: It would be preferable to put these at the bottom of the file under the export options heading, but it seems that "TEXINFO_DIR_CATEGORY" only works at the top of the file.

+EXPORT_FILE_NAME: plz.texi

+TEXINFO_DIR_CATEGORY: Emacs

+TEXINFO_DIR_TITLE: Plz: (plz)

+TEXINFO_DIR_DESC: HTTP library using Curl as a backend

Note: This readme works with the org-make-toc https://github.com/alphapapa/org-make-toc package, which automatically updates the table of contents.

[[http://elpa.gnu.org/packages/plz.html][file:http://elpa.gnu.org/packages/plz.svg]]

+HTML:

~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 [[https://httpbin.org/][httpbin]].

** GNU ELPA

~plz~ is available in [[http://elpa.gnu.org/packages/plz.html][GNU ELPA]]. It may be installed in Emacs using the ~package-install~ command.

** Manual

~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)~.

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.

** Examples

Synchronously =GET= a URL and return the response body as a decoded string (here, raw JSON):

+BEGIN_SRC elisp :exports both :results value code :cache yes

(plz 'get "https://httpbin.org/user-agent")

+END_SRC

+RESULTS[47fef7e4780e9fac6c99d7661c29de580bf0fa14]:

+begin_src elisp

"{\n \"user-agent\": \"curl/7.35.0\"\n}\n"

+end_src

Synchronously =GET= a URL that returns a JSON object, and parse and return it as an alist:

+BEGIN_SRC elisp :exports both :results value code :cache yes

(plz 'get "https://httpbin.org/get" :as #'json-read)

+END_SRC

+RESULTS[a117174ba62b2be3ea3f23e5c43662047b81bccf]:

+begin_src elisp

((args) (headers (Accept . "/") (Accept-Encoding . "deflate, gzip") (Host . "httpbin.org") (User-Agent . "curl/7.35.0")) (url . "https://httpbin.org/get"))

+end_src

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:

+BEGIN_SRC elisp :exports both :cache yes

(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))))

+END_SRC

+RESULTS[3f4fdd16c4980bf36c3930e91f69cc379cca4a35]:

: Result: {"key":"value"}

Synchronously download a JPEG file, then create an Emacs image object from the data:

+BEGIN_SRC elisp :exports both :cache yes

(let ((jpeg-data (plz 'get "https://httpbin.org/image/jpeg" :as 'binary))) (create-image jpeg-data nil 'data))

+END_SRC

+RESULTS[fbe8a6c8cb097ac08e992ea90bdbd50e7337a385]:

: (image :type jpeg :data ""ÿØÿà^@^PJFIF...")

** Functions

** Queueing

~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:

+begin_src elisp :exports code

(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))))

+end_src

Or:

+begin_src elisp :exports code

(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))))))

+end_src

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.

** Tips :PROPERTIES: :TOC: :ignore (this) :END:

** 0.9

Compatibility

Changes

Fixes

Development

** 0.8

Additions

** 0.7.3

Fixes

** 0.7.2

Fixes

** 0.7.1

Fixes

** 0.7

Changes

Fixes

Internal

** 0.6

Additions

Fixes

** 0.5.4

Fixes

** 0.5.3

Fixes

** 0.5.2

Fixes

** 0.5.1

Fixes

** 0.5

Additions

** 0.4

Additions

Changes

Fixes

Internal

** 0.3

Additions

Fixes

** 0.2.1

Fixes

** 0.2

Added

** 0.1

Initial release.

Bug reports, feature requests, suggestions — /oh my/!

Note that ~plz~ is a young library, and its only client so far is [[https://github.com/alphapapa/ement.el][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.

** Copyright assignment

This package is part of [[https://www.gnu.org/software/emacs/][GNU Emacs]], being distributed in [[https://elpa.gnu.org/][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 [[mailto:emacs-devel@gnu.org][emacs-devel@gnu.org]] to request the assignment form.

GPLv3

Copied from org-super-agenda's readme, in which much was borrowed from Org's =org-manual.org=.

+OPTIONS: broken-links:t *:t

** Info export options

NOTE: These are moved to the top of the file.

** File-local variables

NOTE: Setting org-comment-string buffer-locally is a nasty hack to work around GitHub's org-ruby's HTML rendering, which does not respect noexport tags. The only way to hide this tree from its output is to use the COMMENT keyword, but that prevents Org from processing the export options declared in it. So since these file-local variables don't affect org-ruby, wet set org-comment-string to an unused keyword, which prevents Org from deleting this tree from the export buffer, which allows it to find the export options in it. And since org-export does respect the noexport tag, the tree is excluded from the info page.

Local Variables:

eval: (require 'org-make-toc)

before-save-hook: org-make-toc

org-export-with-properties: ()

org-export-with-title: t

org-export-initial-scope: buffer

org-comment-string: "NOTCOMMENT"

End: