diff options
| author | Peder O. Klingenberg | 2025-07-18 00:11:57 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2025-07-26 12:09:07 +0300 |
| commit | a2d71cecaec1aa16bbbef54e5231ba203e7d2a2a (patch) | |
| tree | 8b6294bfff23640d64164dda98a600463c49c176 | |
| parent | 44bb860796a0537bc0df2f6b603153989c7957a0 (diff) | |
| download | emacs-a2d71cecaec1aa16bbbef54e5231ba203e7d2a2a.tar.gz emacs-a2d71cecaec1aa16bbbef54e5231ba203e7d2a2a.zip | |
Emulate more dynamic bindings in request buffers
Many variables were copied from the dynamic environment to the request
buffer, which allowed them to influence the handling of requests and
responses. But some were not, notably some of the mime-related
variables, and the user-agent and privacy variables. This made them
unreliable when dynamically bound around a call to `url-retrieve'; they
would have the desired effect when reusing an existing connection, but
not when url-http opened a new connection. In the case of reused
connections, the request construction happens in the dynamic scope of
`url-http', but in the case where a fresh connection is needed, request
construction happens outside that dynamic scope.
This commit adds the remaining variables used in request construction to
the set of buffer local variables mirroring the dynamic values from
url-http, and adds a comment describing the mechanism used and how avoid
the pitfall of inconsistent handling of dynamic bindings.
* lisp/url/url-http.el (url-http-extensions-header): New internal-ish
variable.
(url-http-create-request): Use the new variable instead of the global
one.
(url-http-idle-sentinel): Debug-log when the connection closes.
(url-http): Set up more buffer-local variants of dynamic variables in
the buffer used for the request, and add comment describing why this
copying is needed.
(Bug#61916)
| -rw-r--r-- | lisp/url/url-http.el | 51 |
1 files changed, 44 insertions, 7 deletions
diff --git a/lisp/url/url-http.el b/lisp/url/url-http.el index eb5d5c13722..a230a37e9ff 100644 --- a/lisp/url/url-http.el +++ b/lisp/url/url-http.el | |||
| @@ -56,6 +56,7 @@ | |||
| 56 | (defvar url-http-transfer-encoding) | 56 | (defvar url-http-transfer-encoding) |
| 57 | (defvar url-show-status) | 57 | (defvar url-show-status) |
| 58 | (defvar url-http-referer) | 58 | (defvar url-http-referer) |
| 59 | (defvar url-http-extensions-header) | ||
| 59 | 60 | ||
| 60 | (require 'url-gw) | 61 | (require 'url-gw) |
| 61 | (require 'url-parse) | 62 | (require 'url-parse) |
| @@ -374,9 +375,9 @@ Use `url-http-referer' as the Referer-header (subject to `url-privacy-level')." | |||
| 374 | "close" "keep-alive") | 375 | "close" "keep-alive") |
| 375 | "\r\n" | 376 | "\r\n" |
| 376 | ;; HTTP extensions we support | 377 | ;; HTTP extensions we support |
| 377 | (if url-extensions-header | 378 | (if url-http-extensions-header |
| 378 | (format | 379 | (format |
| 379 | "Extension: %s\r\n" url-extensions-header)) | 380 | "Extension: %s\r\n" url-http-extensions-header)) |
| 380 | ;; Who we want to talk to | 381 | ;; Who we want to talk to |
| 381 | (if (/= (url-port url-http-target-url) | 382 | (if (/= (url-port url-http-target-url) |
| 382 | (url-scheme-get-property | 383 | (url-scheme-get-property |
| @@ -1020,8 +1021,9 @@ should be shown to the user." | |||
| 1020 | ;; ) | 1021 | ;; ) |
| 1021 | 1022 | ||
| 1022 | ;; These unfortunately cannot be macros... please ignore them! | 1023 | ;; These unfortunately cannot be macros... please ignore them! |
| 1023 | (defun url-http-idle-sentinel (proc _why) | 1024 | (defun url-http-idle-sentinel (proc why) |
| 1024 | "Remove (now defunct) process PROC from the list of open connections." | 1025 | "Remove (now defunct) process PROC from the list of open connections." |
| 1026 | (url-http-debug "url-http-idle-sentinel for process %S: %s" proc (string-trim why)) | ||
| 1025 | (maphash (lambda (key val) | 1027 | (maphash (lambda (key val) |
| 1026 | (if (memq proc val) | 1028 | (if (memq proc val) |
| 1027 | (puthash key (delq proc val) url-http-open-connections))) | 1029 | (puthash key (delq proc val) url-http-open-connections))) |
| @@ -1340,9 +1342,19 @@ overriding the value of `url-gateway-method'. | |||
| 1340 | 1342 | ||
| 1341 | The return value of this function is the retrieval buffer." | 1343 | The return value of this function is the retrieval buffer." |
| 1342 | (cl-check-type url url "Need a pre-parsed URL.") | 1344 | (cl-check-type url url "Need a pre-parsed URL.") |
| 1345 | ;; The request is handled by asynchronous processes, which are outside | ||
| 1346 | ;; the dynamic scope of the caller of url-http (sometimes, sometimes | ||
| 1347 | ;; not). The caller may still desire to bind variables controlling | ||
| 1348 | ;; aspects of the request for the duration of this one http request. | ||
| 1349 | ;; The async processes operate on a buffer created in this function, | ||
| 1350 | ;; so the way to accomplish this goal is to set buffer local copies of | ||
| 1351 | ;; the relevant variables to the dynamic values in scope as we create | ||
| 1352 | ;; the buffer. When new variables are added that influence behaviour | ||
| 1353 | ;; of requests, they should be added to the handling in this function | ||
| 1354 | ;; to make them work reliably without changing their global values. | ||
| 1343 | (let* (;; (host (url-host (or url-using-proxy url))) | 1355 | (let* (;; (host (url-host (or url-using-proxy url))) |
| 1344 | ;; (port (url-port (or url-using-proxy url))) | 1356 | ;; (port (url-port (or url-using-proxy url))) |
| 1345 | (nsm-noninteractive (not (url-interactive-p))) | 1357 | (noninteractive-p (not (url-interactive-p))) |
| 1346 | ;; The following binding is needed in url-open-stream, which | 1358 | ;; The following binding is needed in url-open-stream, which |
| 1347 | ;; is called from url-http-find-free-connection. | 1359 | ;; is called from url-http-find-free-connection. |
| 1348 | (url-current-object url) | 1360 | (url-current-object url) |
| @@ -1350,10 +1362,17 @@ The return value of this function is the retrieval buffer." | |||
| 1350 | (url-port url) | 1362 | (url-port url) |
| 1351 | gateway-method)) | 1363 | gateway-method)) |
| 1352 | (mime-accept-string url-mime-accept-string) | 1364 | (mime-accept-string url-mime-accept-string) |
| 1365 | (mime-encoding-string url-mime-encoding-string) | ||
| 1366 | (mime-charset-string url-mime-charset-string) | ||
| 1367 | (mime-language-string url-mime-language-string) | ||
| 1353 | (buffer (or retry-buffer | 1368 | (buffer (or retry-buffer |
| 1354 | (generate-new-buffer | 1369 | (generate-new-buffer |
| 1355 | (format " *http %s:%d*" (url-host url) (url-port url))))) | 1370 | (format " *http %s:%d*" (url-host url) (url-port url))))) |
| 1356 | (referer (url-http--encode-string (url-http--get-referer url)))) | 1371 | (referer (url-http--encode-string (url-http--get-referer url))) |
| 1372 | (httpver url-http-version) | ||
| 1373 | (httpkeepalive url-http-attempt-keepalives) | ||
| 1374 | (user-agent url-user-agent) | ||
| 1375 | (privacy-level url-privacy-level)) | ||
| 1357 | (if (not connection) | 1376 | (if (not connection) |
| 1358 | ;; Failed to open the connection for some reason | 1377 | ;; Failed to open the connection for some reason |
| 1359 | (progn | 1378 | (progn |
| @@ -1389,8 +1408,17 @@ The return value of this function is the retrieval buffer." | |||
| 1389 | url-http-no-retry | 1408 | url-http-no-retry |
| 1390 | url-http-connection-opened | 1409 | url-http-connection-opened |
| 1391 | url-mime-accept-string | 1410 | url-mime-accept-string |
| 1411 | url-mime-encoding-string | ||
| 1412 | url-mime-charset-string | ||
| 1413 | url-mime-language-string | ||
| 1392 | url-http-proxy | 1414 | url-http-proxy |
| 1393 | url-http-referer)) | 1415 | url-http-referer |
| 1416 | url-http-version | ||
| 1417 | url-http-attempt-keepalives | ||
| 1418 | url-http-extensions-header | ||
| 1419 | url-user-agent | ||
| 1420 | url-privacy-level | ||
| 1421 | nsm-noninteractive)) | ||
| 1394 | (set (make-local-variable var) nil)) | 1422 | (set (make-local-variable var) nil)) |
| 1395 | 1423 | ||
| 1396 | (setq url-http-method (or url-request-method "GET") | 1424 | (setq url-http-method (or url-request-method "GET") |
| @@ -1409,8 +1437,17 @@ The return value of this function is the retrieval buffer." | |||
| 1409 | url-http-no-retry retry-buffer | 1437 | url-http-no-retry retry-buffer |
| 1410 | url-http-connection-opened nil | 1438 | url-http-connection-opened nil |
| 1411 | url-mime-accept-string mime-accept-string | 1439 | url-mime-accept-string mime-accept-string |
| 1440 | url-mime-encoding-string mime-encoding-string | ||
| 1441 | url-mime-charset-string mime-charset-string | ||
| 1442 | url-mime-language-string mime-language-string | ||
| 1412 | url-http-proxy url-using-proxy | 1443 | url-http-proxy url-using-proxy |
| 1413 | url-http-referer referer) | 1444 | url-http-referer referer |
| 1445 | url-http-version httpver | ||
| 1446 | url-http-attempt-keepalives httpkeepalive | ||
| 1447 | url-http-extensions-header url-extensions-header | ||
| 1448 | url-user-agent user-agent | ||
| 1449 | url-privacy-level privacy-level | ||
| 1450 | nsm-noninteractive noninteractive-p) | ||
| 1414 | 1451 | ||
| 1415 | (set-process-buffer connection buffer) | 1452 | (set-process-buffer connection buffer) |
| 1416 | (set-process-filter connection #'url-http-generic-filter) | 1453 | (set-process-filter connection #'url-http-generic-filter) |