branch: externals/plz
commit 8d2654bba7bfa11525aef50f969c489c20ac0a43
Author: Adam Porter <[email protected]>
Commit: Adam Porter <[email protected]>
Add/Change: Handle LF-only HTTP responses
Seems that some Cloudflare responses from the matrix.org server are
using only LF characters between the headers and body (while RFC 2616
requires CRLF). So, rather than fail completely or return invalid
data, we try to accommodate either CRLF or LF-only, but in the latter
case we display a warning (hoping that it will help to understand this
issue and can eventually be removed).
---
plz.el | 36 +++++++++++++++++++++++++++++++-----
1 file changed, 31 insertions(+), 5 deletions(-)
diff --git a/plz.el b/plz.el
index 097e43d420..8e22d037ff 100644
--- a/plz.el
+++ b/plz.el
@@ -559,7 +559,9 @@ according to the apparent coding system."
(save-excursion
(goto-char (point-min))
;; Parse HTTP version and status code.
- (looking-at plz-http-response-status-line-regexp)
+ (unless (looking-at plz-http-response-status-line-regexp)
+ (error "Unable to parse HTTP response status line: %S"
+ (substring-no-properties (buffer-string))))
(let* ((http-version (string-to-number (match-string 1)))
(status-code (string-to-number (match-string 2)))
(headers (plz--headers))
@@ -584,10 +586,14 @@ refer to rather than the current buffer's unparsed
headers."
(defun plz--http-status ()
"Return HTTP status code for HTTP response in current buffer."
+ ;; This function is used in the sentinel to get the HTTP response
+ ;; code without parsing the whole response.
(save-excursion
(goto-char (point-min))
- (when (looking-at plz-http-response-status-line-regexp)
- (string-to-number (match-string 2)))))
+ (unless (looking-at plz-http-response-status-line-regexp)
+ (error "Unable to parse HTTP response status line: %S"
+ (substring-no-properties (buffer-string))))
+ (string-to-number (match-string 2))))
(defun plz--headers ()
"Return headers alist for HTTP response in current buffer."
@@ -595,7 +601,7 @@ refer to rather than the current buffer's unparsed headers."
(goto-char (point-min))
(forward-line 1)
(let ((limit (save-excursion
- (re-search-forward "^\r\n" nil)
+ (plz--skip-headers)
(point))))
(cl-loop while (re-search-forward (rx bol (group (1+ (not (in ":"))))
":" (1+ blank)
(group (1+ (not (in "\r\n")))))
@@ -607,10 +613,30 @@ refer to rather than the current buffer's unparsed
headers."
;; use `alist-get' without having to add "nil nil #'equal"
every time.
collect (cons (intern (downcase (match-string 1)))
(match-string 2))))))
+(defun plz--skip-headers ()
+ "Move point past headers in current HTTP response buffer.
+It seems that some misbehaving HTTP servers use only LF line
+endings rather than the RFC 2616-mandated CRLF endings, so we
+must try to handle either."
+ ;; It seems that this is happening with some Cloudflare responses. :(
+ ;; NOTE: For debugging purposes, I'm inserting these warnings for now. If
this is a solvable
+ ;; bug, or if I come to understand the issue better, they could be removed
or disabled.
+ (condition-case _err
+ (re-search-forward "^\r\n" nil)
+ (search-failed ;; Try LF-only.
+ (condition-case _err
+ (progn
+ (re-search-forward "^\n" nil)
+ (display-warning 'plz (format "Only LF used after headers in HTTP
response: %S"
+ (substring-no-properties
(buffer-string)))))
+ (search-failed
+ (signal 'search-failed (format "Can't find end-of-headers in HTTP
response: %S"
+ (substring-no-properties
(buffer-string)))))))))
+
(defun plz--narrow-to-body ()
"Narrow to body of HTTP response in current buffer."
(goto-char (point-min))
- (re-search-forward "^\r\n" nil)
+ (plz--skip-headers)
(narrow-to-region (point) (point-max)))
;;;; Footer