Skip to content

Commit

Permalink
Parse multiline URLs
Browse files Browse the repository at this point in the history
  • Loading branch information
federicotdn committed Jun 25, 2024
1 parent a9c668a commit d96ffeb
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- Improved `*Verb Log*` buffer formatting.
- Headers can now contain code tags that expand to multiple lines.
- Escape sequences ('\\') contained in strings resulting from evaluating code tags will not be interepreted, i.e. all contents will be taken as literal.
- URLs can now span multiple lines, place '\\' at the end of the URL line to continue it in the next one. Leading whitespace in the additional lines will be skipped.

## **2.16.0** - 2024-03-02 (MELPA Stable)
- Fixed LF being used instead of CRLF in multipart boundaries.
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ test: clean server-bg
--eval "(ert-run-tests-batch-and-exit '$(SELECTOR))"; \
ret=$$?; \
make server-kill; \
sleep 1; \
exit $$ret

server: ## Run a testing HTTP server on port 8000 (default).
Expand Down
26 changes: 26 additions & 0 deletions test/verb-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,32 @@
(list (cons "Foo-Bar" "text")
(cons "Referer" "host.com")))))

(ert-deftest test-request-spec-from-text-url-backslash ()
(setq aux (text-as-spec-nl "get http://example.com?\\"
"a=b"))
(should (string= (verb-request-spec-url-to-string aux)
"http://example.com/?a=b"))

(setq aux (text-as-spec-nl "get http://example.com?\\"
" a=b"))
(should (string= (verb-request-spec-url-to-string aux)
"http://example.com/?a=b"))

(setq aux (text-as-spec-nl "get http://example.com?\\"
" a=b&\\"
"\t\t\t\tc=d"))
(should (string= (verb-request-spec-url-to-string aux)
"http://example.com/?a=b&c=d"))

(should-error
(text-as-spec-nl "get http://example.com?\\"))
(should-error
(text-as-spec-nl "get http://example.com?\\"
"foobar\\"))
(should-error
(text-as-spec-nl "get http://example.com?\\"
" ")))

(ert-deftest test-request-spec-from-text-body-trailing-chars ()
(setq aux (text-as-spec-nl "GET example.com"
"Accept: text"
Expand Down
45 changes: 35 additions & 10 deletions verb.el
Original file line number Diff line number Diff line change
Expand Up @@ -2457,7 +2457,7 @@ METADATA."
(insert text)
(goto-char (point-min))

;;; COMMENTS / PROPERTIES
;;; COMMENTS + PROPERTIES

;; Skip initial blank lines, comments and properties
(while (and (re-search-forward "^\\s-*\\(\\(:\\|#\\).*\\)?$"
Expand All @@ -2474,23 +2474,48 @@ METADATA."

;; Read HTTP method and URL line
;; First, expand any code tags on it (if any)
(let ((case-fold-search t)
(line (verb--eval-code-tags-in-string
(buffer-substring-no-properties (point)
(line-end-position))
context)))
(let* ((case-fold-search t)
(get-line-fn (lambda ()
(verb--eval-code-tags-in-string
(buffer-substring-no-properties
(point) (line-end-position))
context)))
(line (funcall get-line-fn)))
;; Try to match:
;; A) METHOD URL
;; B) METHOD
(if (string-match (concat "^\\s-*\\("
(verb--http-methods-regexp)
"\\)\\s-+\\(.+\\)$")
line)
;; Matched method + URL, store them
(setq method (upcase (match-string 1 line))
url (match-string 2 line))
;; A) Matched method + URL, store them
(progn
(setq method (upcase (match-string 1 line))
url (string-remove-suffix "\\" (match-string 2 line)))

;; Subcase:
;; If URL ends with '\', append following lines to it
;; until one of them does not end with '\' (ignoring
;; leading whitespace, for alignment).
(while (string-suffix-p "\\" line)
(end-of-line)
(if (eobp)
(user-error
"Backslash was not followed by additional line")
(forward-char))
(back-to-indentation)
(setq line (funcall get-line-fn))
(when (string-empty-p line)
(user-error
"Backslash was not followed by additional content"))

(setq url (concat url (string-remove-suffix "\\" line)))))

(when (string-match (concat "^\\s-*\\("
(verb--http-methods-regexp)
"\\)\\s-*$")
line)
;; Matched method only, store it
;; B) Matched method only, store it
(setq method (upcase (match-string 1 line))))))

;; We've processed the URL line, move to the end of it
Expand Down

0 comments on commit d96ffeb

Please sign in to comment.