[emacs-berlin] Code review for a simple HTTP async client
jman
emacs-berlin at city17.xyz
Tue Jan 2 15:18:25 UTC 2024
Today I decided to get to the bottom of it, so here we are with what I
believe is the correct solution :-)
Due to the single-threaded nature of Emacs, handling async tasks is
unwieldy. Opting for a sync HTTP client is equally not great because the
entire UI would block until the operation completes. And since this
involves a remote server, the waiting is undefined (could even timeout
at 30 seconds).
The only way I could make it work reliably was to remove the global
variable and put the Location URL from the header into the kill ring.
----------s---------s----------
(defun jman/http-head-no-redirect (url)
"Sends an HTTP HEAD request to URL, don't follow redirects.
Parse the response headers and put the Location into the kill ring."
(defvar url-request-method "HEAD")
(defvar url-user-agent "User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +google.com/bot.html)")
(let ()
(url-retrieve
url
(lambda (status)
(when (eq (car status) :redirect)
(let ((location (cadr status)))
(message "URL: %s" location)
(kill-new location)))))))
----------e---------e----------
The caller of the async function should not attempt to do anything with
the result because it will always finish ealier.
----------s---------s----------
(defun jman/clean-links (url)
(interactive (list (shr-url-at-point current-prefix-arg)))
(jman/http-head-no-redirect url)
;; This point is reached before the task above line has finished
)
----------e---------e----------
By the way, Doom Emacs ships with async.el[0] but I prefer a solution
that works with the Emacs standard library.
[0]: https://github.com/jwiegley/emacs-async
More information about the emacs-berlin
mailing list