标题: plz.el
属性: LOGGING nil
注意:最好将这些内容放在文件底部的导出选项标题下,但似乎"TEXINFO_DIR_CATEGORY"只在文件顶部有效。
EXPORT_FILE_NAME: plz.texi
TEXINFO_DIR_CATEGORY: Emacs
TEXINFO_DIR_TITLE: Plz: (plz)
TEXINFO_DIR_DESC: 使用Curl作为后端的HTTP库
注意:本README与org-make-toc https://github.com/alphapapa/org-make-toc包配合使用,该包会自动更新目录。
[[http://elpa.gnu.org/packages/plz.html][file:http://elpa.gnu.org/packages/plz.svg]]
#+HTML:
plz是一个Emacs的HTTP库。它使用curl作为后端,避免了使用Emacs内置url库的一些问题。它支持同步和异步请求。其API旨在简单、自然且富有表现力。其代码旨在简洁且组织良好。每个功能都经过[[https://httpbin.org/][httpbin]]的测试。
- 目录 :noexport: :PROPERTIES: :TOC: :include siblings :END: :CONTENTS:
- [[#installation][安装]]
- [[#usage][使用]]
- [[#examples][示例]]
- [[#functions][函数]]
- [[#queueing][队列]]
- [[#changelog][更新日志]]
- [[#credits][致谢]]
- [[#development][开发]]
- [[#copyright-assignment][版权声明]] :END:
- 安装 :PROPERTIES: :TOC: :depth 0 :END:
** GNU ELPA
plz可在[[http://elpa.gnu.org/packages/plz.html][GNU ELPA]]中获取。可以在Emacs中使用package-install命令安装。
** 手动安装
plz除了Emacs和curl外没有其他依赖。它已知可在Emacs 26.3或更高版本上运行。要手动安装,只需将=plz.el=放入您的load-path中,然后执行~(require 'plz)~。
- 使用 :PROPERTIES: :TOC: :depth 1 :END:
主要的公共函数是plz,它发送HTTP请求并返回指定类型的结果(对于同步请求),或curl进程对象(对于异步请求)。对于异步请求,可以指定回调函数、错误处理函数和终结器函数,以及各种其他选项。
** 示例
同步GET一个URL并将响应体作为解码后的字符串返回(这里是原始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
同步GET一个返回JSON对象的URL,并将其解析并作为关联列表返回:
#+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
异步POST一个JSON对象在请求体中,然后从响应体中解析JSON对象,并用结果调用一个函数:
#+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"}
同步下载一个JPEG文件,然后从数据创建一个Emacs图像对象:
#+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...")
** 函数
-
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))/使用curl请求
URL的METHOD。返回curl进程对象,或对于同步请求,返回选定的结果。HEADERS可以是一个与请求一起发送的额外头部的关联列表。BODY可以是一个字符串、一个缓冲区,或者像~(file FILENAME)~这样的列表,用于从磁盘上传文件。BODY-TYPE可以是text以文本形式发送BODY,或binary以二进制形式发送。AS选择要传递给回调函数THEN的结果类型,或同步请求要返回的结果类型。它可以是:buffer传递响应缓冲区,该缓冲区将被缩小到响应体并根据DECODE进行解码。binary将响应体作为未解码的字符串传递。string将响应体作为解码后的字符串传递。response传递一个plz-response结构。file传递一个临时文件名,响应体已被保存到该文件中而未解码。(fileexpand-file-name~处理,请参见该函数。FILENAME)后传递它,而不解码。在将响应体保存到FILENAMEFILENAME必须是不存在的文件;如果它存在,将不会被覆盖,并会发出错误信号。FILENAME通过- 一个函数,在响应缓冲区中调用,并将其缩小到响应体(适用于例如
json-read)。
如果
DECODE为非nil,响应体会自动解码。对于二进制内容,它应该为nil。当AS为binary时,DECODE自动设置为nil。THEN是一个回调函数,其唯一参数由上面的AS选择;如果请求失败且未给出ELSE函数(见下文),参数将是描述错误的plz-error结构。或者THEN可以是sync以进行同步请求,在这种情况下,结果直接从这个函数返回。ELSE是一个可选的回调函数,在请求失败时调用(即如果curl失败,或者如果HTTP响应有非2xx状态码)。它以一个plz-error结构作为参数调用。如果ELSE为nil,当请求失败时会发出plz-curl-error或plz-http-error信号,并带有plz-error结构作为错误数据。对于同步请求,此参数被忽略。注意:在plz的v0.8版本中,只会发出一个错误信号:plz-error。现有的错误,plz-curl-error和plz-http-error,继承自plz-error,以允许应用程序在使用v0.7时更新其代码(即任何condition-case形式现在应该只处理plz-error,而不是其他两个)。FINALLY是一个可选函数,在THEN或ELSE之后适当调用,不带参数。对于同步请求,此参数被忽略。CONNECT-TIMEOUT和TIMEOUT是限制连接到主机和从主机接收响应所需时间的秒数。NOQUERY传递给make-process,请参见该函数。FILTER是一个可选函数,用作 curl 进程的过滤器。它可以用于以流式方式处理 HTTP 响应。该函数必须接受两个参数:运行 curl 的进程对象,以及从进程接收到的输出字符串。默认的进程过滤器将进程的输出插入到进程缓冲区中。提供的FILTER函数至少应将输出插入到进程缓冲区中直到 HTTP 正文部分。
** 队列
plz 提供了一个简单的系统来队列 HTTP 请求。首先,通过调用 make-plz-queue 创建一个 plz-queue 结构体。然后用该结构体作为第一个参数调用 plz-queue,其余参数与传递给 plz 的参数相同。最后调用 plz-run 来运行队列中的请求。
所有与队列相关的函数都返回队列作为它们的值,使其易于使用。例如:
#+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
或者:
#+begin_src elisp :exports code (let ((queue (make-plz-queue :limit 2 :finally (lambda () (message "队列为空。")))) (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
你也可以用 plz-clear 清空队列,它会取消任何活动或排队的请求并调用它们的 :else 函数。plz-length 返回队列中活动和排队请求的数量。
** 提示
- 你可以在 =plz= 组中自定义设置,但这只能用于调整一些默认值。正常操作不需要更改或绑定全局变量。
- 更新日志
** 0.10-pre
暂无新内容。
** 0.9.1
修复
- 下载到文件时展开文件名(这已经应用于上传时传递的文件名)。(感谢 [[https://github.com/josephmturner][Joseph Turner]])
** 0.9
兼容性
- 现在支持的最低 Emacs 版本为 27.1。(不再实际测试
plz与早于 27.1 的 Emacs 版本。对于 Emacs 26.3,可以使用早期版本的plz,或者此版本可能兼容,无需或仅需少量修改,但维护者不提供支持。)
新增
- 下载到文件时,会向 Curl 传递
--create-dirs选项,以便自动创建任何必要的子目录。([[https://github.com/alphapapa/plz.el/pull/64][#64]]。感谢 [[https://github.com/josephmturner][Joseph Turner]] 和 [[https://ushin.org/][USHIN]])
更改
- 移除
plz-timeout选项。(它是plz的:timeout参数的默认值,该参数传递给 Curl 作为其--max-time参数,限制请求操作的总持续时间。此参数默认应未设置,因为较大或较慢的下载可能无法在特定时间内完成,默认设置此选项对用户来说是出乎意料的,可能导致请求不必要地超时。) - 使用参数
:as 'file或:as '(file FILENAME)现在将文件名传递给 Curl,允许它直接将数据写入文件(而不是将数据接收到 Emacs 缓冲区然后写入文件。这在下载大文件时提高了性能,显著减少了 Emacs 的 CPU 和内存使用)。
修复
- 改进了对 Emacs 进程哨兵相关问题的解决方案。(如果 Emacs 在
plz为同步请求返回后调用哨兵,则不尝试第二次处理响应。参见 [[https://github.com/alphapapa/plz.el/issues/53][#53]]。感谢 [[https://github.com/josephmturner][Joseph Turner]] 的大量调试帮助,以及 [[https://ushin.org/][USHIN]] 赞助的部分工作。) - 调用
generate-new-buffer时禁用缓冲区钩子(作为额外保护,防止在出错时出现"kill buffer?"提示)。(参见 [[https://github.com/alphapapa/plz.el/pull/52][#52]]。感谢 [[https://github.com/mkcms][Michał Krzywkowski]]。)- 在 Emacs 28 之前的版本中,避免在出错时出现"kill buffer?"提示。(参见 [[https://github.com/alphapapa/plz.el/pull/52][#52]] 和 [[https://github.com/alphapapa/plz.el/issues/57][#57]]。感谢 [[https://github.com/mkcms][Michał Krzywkowski]]。)
开发
plz现在自动测试 Emacs 版本 27.1、27.2、28.1、28.2、29.1、29.2、29.3 和master分支的最新快照(新增 29.2 和 29.3)。
** 0.8
新增
- 函数
plz现在接受:filter参数,可用于覆盖默认的进程过滤器(例如用于流式响应)。([[https://github.com/alphapapa/plz.el/pull/43][#43]], [[https://github.com/alphapapa/plz.el/pull/50][#50]]。感谢 [[https://github.com/r0man][Roman Scherer]]。)
** 0.7.3
修复
- 修复在 GNU ELPA 上生成 Info 手册的问题。(同时,Info 手册不再提交到 Git。)
** 0.7.2
修复
- 下载到文件时不删除预先存在的文件。([[https://github.com/alphapapa/plz.el/pull/41][#41]]。感谢 [[https://github.com/josephmturner][Joseph Turner]]。)
** 0.7.1
修复
- 处理 HTTP 303 重定向。(感谢 [[https://github.com/hubisan][Daniel Hubmann]] 的报告。)
** 0.7
更改
-
定义了一个新的错误信号
plz-error。现有的信号plz-curl-error和plz-http-error继承自它,因此处理plz-error可以捕获这两种错误。注意: 现有的信号
plz-curl-error和plz-http-error在此被废弃,它们将在 v0.8 中移除。应用程序应在使用 v0.7 时更新,只期望plz-error。
修复
- 通过实施故障保护和解决 Emacs 进程处理代码的问题,显著提高了可靠性。(参见 [[https://github.com/alphapapa/plz.el/issues/3][#3]]。)
- curl 进程的 STDERR 输出不再包含在响应正文中(这种情况有时会发生,取决于 Emacs 的内部竞争条件)。(修复 [[https://github.com/alphapapa/plz.el/issues/23][#23]]。)
- 对同步请求使用
with-local-quit(防止 Emacs 有时抱怨)。(修复 [[https://github.com/alphapapa/plz.el/issues/26][#26]]。) - 对
:as 'buffer结果类型进行了各种修复:在适当时解码正文;对二进制设置非多字节;缩小到正文;不过早杀死缓冲区。 - 清空队列时,不尝试杀死已完成的进程。
内部
- 响应处理现在在进程哨兵之外进行,因此任何错误(例如在用户回调中)不会从哨兵内部发出信号。(这避免了 Emacs 在这种情况下强加的 2 秒暂停。)
- 测试运行在 [[https://github.com/postmanlabs/httpbin][httpbin]] 的本地实例上(因为
httpbin.org服务器经常过载)。 - 不再定义缓冲区局部变量;改用进程属性。
** 0.6
新增
- 函数
plz的:body参数现在接受一个类似(file FILENAME)的列表,用于从磁盘上传文件(通过将文件名传递给 curl,而不是将其内容读入 Emacs 并通过管道发送给 curl)。
修复
- 函数
plz的文档字符串现在提到:body参数也可以是一个缓冲区(这是一个有意的功能,但意外地未记录)。 - 使用
:as 'response时处理 HTTP 3xx 重定向。
** 0.5.4 修复
- 仅在队列为空后运行队列的
finally函数。(新功能不应在周五设计和发布。)
** 0.5.3
修复
- 将
plz-queue结构中的新槽移至末尾,以防止已编译应用程序的无效字节编译器扩展(这需要在升级plz后重新编译它们)。
** 0.5.2
修复
- 清除队列时,仅在指定时调用
plz-queue的finally函数。
** 0.5.1
修复
- 仅在指定时调用
plz-queue的finally函数。(感谢 [[https://github.com/redchops][Dan Oriani]] 报告。)
** 0.5
新增
plz-queue结构的finally槽,一个在队列完成时调用的函数。
** 0.4
新增
- 支持 HTTP
HEAD请求。(感谢 [[https://ushin.org/][USHIN]] 赞助。)
变更
- 允许发送无主体的
POST和PUT请求。([[https://github.com/alphapapa/plz.el/issues/16][#16]]。感谢 [[https://github.com/josephmturner][Joseph Turner]] 报告。感谢 [[https://ushin.org/][USHIN]] 赞助。)
修复
- 所有 2xx HTTP 状态码都被视为成功。([[https://github.com/alphapapa/plz.el/issues/17][#17]]。感谢 [[https://github.com/josephmturner][Joseph Turner]] 报告。感谢 [[https://ushin.org/][USHIN]] 赞助。)
- 错误信号包含正确的错误数据。
内部
- 测试套件明确测试 HTTP/1.1 和 HTTP/2。
- 测试套件还测试 Emacs 版本 27.2、28.1 和 28.2。
** 0.3
新增
- 处理来自 Curl 的 HTTP 代理头。([[https://github.com/alphapapa/plz.el/issues/2][#2]]。感谢 [[https://github.com/alanthird][Alan Third]] 和 [[https://github.com/sawyerzheng][Sawyer Zheng]] 报告。)
修复
- 替换了 Ispell 默认词典中没有的单词(以使
checkdoc检查通过)。
** 0.2.1
修复
- 处理 Curl 进程被中断的情况。
** 0.2
新增
- 简单的请求队列。
** 0.1
初始发布。
- 致谢
- 感谢 [[https://github.com/skeeto][Chris Wellons]],[[https://github.com/skeeto/elfeed][Elfeed]] 订阅阅读器的作者和热门博客 [[https://nullprogram.com/][null program]] 的作者,感谢他宝贵的建议、审查和鼓励。
- 开发
错误报告、功能请求、建议 — 真是太好了!
请注意,plz 是一个年轻的库,目前它唯一的客户端是 [[https://github.com/alphapapa/ement.el][Ement.el]]。有许多 HTTP 和 curl 功能它还不支持,因为作者还没有需要它们。欢迎提交补丁,只要它们包含通过的测试。
** 版权转让
这个包是 [[https://www.gnu.org/software/emacs/][GNU Emacs]] 的一部分,在 [[https://elpa.gnu.org/][GNU ELPA]] 中分发。对这个项目的贡献必须遵循 GNU 的指导原则,这意味着,与 Emacs 的其他部分一样,超过几行的补丁必须附带将贡献的版权转让给 FSF。希望这样做的贡献者可以联系 [[mailto:emacs-devel@gnu.org][emacs-devel@gnu.org]] 请求转让表格。
- 许可证
GPLv3