elisp 语法求教,关于 url.el

使用 url.el 发送请求的时候,碰到一个奇怪的问题。百思不得其解,所以来请教各位。

这是一段使用 url.el 处理文件上传的示例代码。因为是文件内容,所以请求方法为 POST。 在 url.el 中,是通过 url-request-method 的方式指定请求方法:

(defun gt-multipart-data (file)
  "拼接 multipart 格式请求体"
  (with-temp-buffer
    (set-buffer-multibyte nil)
    (insert-file-contents-literally file)
    (concat "--my-boundary-111\r\n"
            "Content-Disposition: form-data; name=\"file\"\r\n\r\n"
            (buffer-substring-no-properties (point-min) (point-max)) "\r\n"
            "--my-boundary-111--")))

;; 发送 post 请求,请求体为 aaa.jpg 文件内容
(let ((url-request-data (gt-multipart-data "~/aaa.jpg"))
      (url-request-extra-headers '(("Content-type" . "multipart/form-data; boundary=my-boundary-111")))
      (url-request-method "POST")                         ; <-- 1
      ;;(url-request-method (upcase (format "%s" 'post))) ; <-- 2
      )
  (url-retrieve "https://httpbin.org/post" (lambda (_) (message "ok"))))

上面代码是可以正常运行的。但奇怪的是,如果将 1 处的代码改为 2,代码却运行不了。报错:

error in process sentinel: Multibyte text in HTTP request: POST /post HTTP/1.1

是我眼花写错了什么吗?还是有别的什么原因?

请大佬指点。

运行环境是 macOS, emacs30。

url.el 关于 Multibyte text in HTTP request 的一件怪事 - Emacs-general - Emacs China (emacs-china.org)

供参考,同时检查一下 url-* 系列参数是否存在 multibyte 字符串,可以用 multibyte-string-p 检查。

即使把代码改成这样,还是同样的错误:

(defun gt-multipart-data (file)
  "拼接 multipart 格式请求体"
  (with-temp-buffer
    (set-buffer-multibyte nil)
    (insert "--my-boundary-111\r\n"
            "Content-Disposition: form-data; name=\"file\"\r\n\r\n")
    (insert-file-contents-literally file)
    (insert "\r\n" "--my-boundary-111--")
    (buffer-string)))

莫名其妙。

我的意思是,检查一下 (upcase (format "%s" 'post))) 是否返回 multibyte 字符串,可以使用 multibyte-string-p 检查。顺便看看其他的参数字符串有没有 multibyte 的 :joy:

顺带,在我的 Emacs 中是这样的结果:

(multibyte-string-p (upcase (format "%s" 'post)))
⇒ nil
2 个赞

我震惊得说不出话。确实没想到是这里的问题……

改成这样就可以了:

(url-request-method (string-to-unibyte (upcase (format "%s" 'post))))

非常感谢。

3 个赞