summaryrefslogtreecommitdiff
path: root/module
diff options
context:
space:
mode:
authorMark H Weaver <mhw@netris.org>2019-06-18 08:26:00 -0400
committerMark H Weaver <mhw@netris.org>2019-06-18 08:28:01 -0400
commit73cde5ed7218a090ecee888870908af5445796f0 (patch)
tree6de77dc2b843e83404261627c01500ab8c652922 /module
parent579dd2da449be194a95d41a27317a453c1aa0568 (diff)
web: Add support for HTTP header continuation lines.
* module/web/http.scm (spaces-and-tabs, space-or-tab?): New variables. (read-header-line): After reading a header, if a space or tab follows, read the continuation lines and join them. * test-suite/tests/web-http.test: Add test.
Diffstat (limited to 'module')
-rw-r--r--module/web/http.scm31
1 files changed, 24 insertions, 7 deletions
diff --git a/module/web/http.scm b/module/web/http.scm
index de61c9495..f1ca733c1 100644
--- a/module/web/http.scm
+++ b/module/web/http.scm
@@ -1,6 +1,6 @@
;;; HTTP messages
-;; Copyright (C) 2010-2017 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2017, 2019 Free Software Foundation, Inc.
;; This library is free software; you can redistribute it and/or
;; modify it under the terms of the GNU Lesser General Public
@@ -152,18 +152,35 @@ The default writer will call ‘put-string’."
(lambda (val port)
(put-string port val)))))
+(define spaces-and-tabs
+ (char-set #\space #\tab))
+
+(define (space-or-tab? c)
+ (case c
+ ((#\space #\tab) #t)
+ (else #f)))
+
(define (read-header-line port)
- "Read an HTTP header line and return it without its final CRLF or LF.
-Raise a 'bad-header' exception if the line does not end in CRLF or LF,
-or if EOF is reached."
+ "Read an HTTP header line, including any continuation lines, and
+return the combined string without its final CRLF or LF. Raise a
+'bad-header' exception if the line does not end in CRLF or LF, or if EOF
+is reached."
(match (%read-line port)
(((? string? line) . #\newline)
;; '%read-line' does not consider #\return a delimiter; so if it's
;; there, remove it. We are more tolerant than the RFC in that we
;; tolerate LF-only endings.
- (if (string-suffix? "\r" line)
- (string-drop-right line 1)
- line))
+ (let ((line (if (string-suffix? "\r" line)
+ (string-drop-right line 1)
+ line)))
+ ;; If the next character is a space or tab, then there's at least
+ ;; one continuation line. Read the continuation lines by calling
+ ;; 'read-header-line' recursively, and append them to this header
+ ;; line, folding the leading spaces and tabs to a single space.
+ (if (space-or-tab? (lookahead-char port))
+ (string-append line " " (string-trim (read-header-line port)
+ spaces-and-tabs))
+ line)))
((line . _) ;EOF or missing delimiter
(bad-header 'read-header-line line))))