使用url-retrieve解码gzip压缩的响应体

6
对于 Emacs 扩展,我想通过 HTTP 获取数据。我不太喜欢使用类似于 wget、curl 或 w3m 等工具来执行该操作的想法,因此我使用 url-retrieve 函数。
我正在与其中一个 HTTP 服务器进行通信,它恰好忽略 Accept-Encoding 标头,并坚持始终使用 Content-Encoding: gzip 发送其数据。
由于这个原因,以及 url-retrieve 不会自动解码响应主体的事实,url-retrieve 提供给我的缓冲区将包含二进制 gzip 数据。
我正在寻找一种方法来解码响应主体,最好是以块的形式随着数据到达而进行解码。有没有办法指示 url-retrieve 为我执行此操作?
一次性完成整个响应的解码也是可接受的,但我宁愿避免创建异步子进程运行 gzip,将我收到的响应的部分传输到该进程,然后读取解码后的块所涉及的所有麻烦 - 我在这里正在寻找一些库功能。

3
显然,Emacs内置了gzip功能,因为你可以打开gzipped文件,对其进行编辑,并透明地保存。问题是……这个挂钩在哪里,答案并不明显。 - jrockway
谢谢,约翰。虽然我知道可以打开gzipped文件,但我真的没有想到这可能是相关的,但显然它是。通过在磁盘上打开.gz文件,查看*Messages*,并搜索我的elisp目录以获取我得到的任何内容,我找出了实现该功能的代码是jka-cmpr-hook.el和/或jka-compr.el。使用这些提供的函数之一很容易解决这个问题。with-auto-compression-mode现在似乎最有前途。 - rafl
有点跑题,但你知道url-retrieve是否可以处理https吗? - sigjuice
为什么不亲自尝试一下呢?(url-retrieve "https://google.com/" #'(lambda (status) (pop-to-buffer (current-buffer)))) - Gareth Rees
1个回答

4
auto-compression-mode 的作用是在要解压缩的文件上运行gzip。例如,请参见jka-compr.el中的jka-compr-insert-file-contents。因此,如果您要使用auto-compression-mode进行解压缩,则需要先将响应写入文件。例如,像这样的内容:
(defun uncompress-callback (status)
  (let ((filename (make-temp-file "download" nil ".gz")))
    (search-forward "\n\n")               ; Skip response headers.
    (write-region (point) (point-max) filename)
    (with-auto-compression-mode
      (find-file filename))))

(url-retrieve "http://packages.ubuntu.com/hardy/allpackages?format=txt.gz"
              #'uncompress-callback)

如果您不想创建临时文件,您需要自己进行子进程管理,但这并不像您在问题中暗示的那样棘手。


如果您正在使用 url-retrieve-synchronously,您只需切换到缓冲区,然后运行该回调即可,您不需要接受状态参数(我会添加 &optional)。 - user9903

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接