mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-09 21:40:33 +02:00
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.
This commit is contained in:
parent
579dd2da44
commit
73cde5ed72
2 changed files with 34 additions and 8 deletions
|
@ -1,6 +1,6 @@
|
||||||
;;; HTTP messages
|
;;; 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
|
;; This library is free software; you can redistribute it and/or
|
||||||
;; modify it under the terms of the GNU Lesser General Public
|
;; 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)
|
(lambda (val port)
|
||||||
(put-string port val)))))
|
(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)
|
(define (read-header-line port)
|
||||||
"Read an HTTP header line and return it without its final CRLF or LF.
|
"Read an HTTP header line, including any continuation lines, and
|
||||||
Raise a 'bad-header' exception if the line does not end in CRLF or LF,
|
return the combined string without its final CRLF or LF. Raise a
|
||||||
or if EOF is reached."
|
'bad-header' exception if the line does not end in CRLF or LF, or if EOF
|
||||||
|
is reached."
|
||||||
(match (%read-line port)
|
(match (%read-line port)
|
||||||
(((? string? line) . #\newline)
|
(((? string? line) . #\newline)
|
||||||
;; '%read-line' does not consider #\return a delimiter; so if it's
|
;; '%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
|
;; there, remove it. We are more tolerant than the RFC in that we
|
||||||
;; tolerate LF-only endings.
|
;; tolerate LF-only endings.
|
||||||
(if (string-suffix? "\r" line)
|
(let ((line (if (string-suffix? "\r" line)
|
||||||
(string-drop-right line 1)
|
(string-drop-right line 1)
|
||||||
line))
|
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
|
((line . _) ;EOF or missing delimiter
|
||||||
(bad-header 'read-header-line line))))
|
(bad-header 'read-header-line line))))
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
;;;; web-http.test --- HTTP library -*- mode: scheme; coding: utf-8; -*-
|
;;;; web-http.test --- HTTP library -*- mode: scheme; coding: utf-8; -*-
|
||||||
;;;;
|
;;;;
|
||||||
;;;; Copyright (C) 2010-2011, 2014-2017 Free Software Foundation, Inc.
|
;;;; Copyright (C) 2010-2011, 2014-2017, 2019 Free Software Foundation, Inc.
|
||||||
;;;;
|
;;;;
|
||||||
;;;; This library is free software; you can redistribute it and/or
|
;;;; This library is free software; you can redistribute it and/or
|
||||||
;;;; modify it under the terms of the GNU Lesser General Public
|
;;;; modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -242,6 +242,15 @@
|
||||||
(pass-if-round-trip "Cache-Control: acme-cache-extension=100 quux\r\n")
|
(pass-if-round-trip "Cache-Control: acme-cache-extension=100 quux\r\n")
|
||||||
(pass-if-round-trip "Cache-Control: acme-cache-extension=\"100, quux\"\r\n")
|
(pass-if-round-trip "Cache-Control: acme-cache-extension=\"100, quux\"\r\n")
|
||||||
|
|
||||||
|
(let ((str "Cache-Control: acme-cache-extension=\"100,\r\n\t foo,\r\n quux\"\r\n")
|
||||||
|
(val '(cache-control . ((acme-cache-extension . "100, foo, quux")))))
|
||||||
|
(pass-if-equal "continuation lines"
|
||||||
|
val
|
||||||
|
(call-with-values (lambda ()
|
||||||
|
(read-header (open-input-string str)))
|
||||||
|
(lambda (sym val)
|
||||||
|
(cons sym val)))))
|
||||||
|
|
||||||
(pass-if-parse connection "close" '(close))
|
(pass-if-parse connection "close" '(close))
|
||||||
(pass-if-parse connection "Content-Encoding" '(content-encoding))
|
(pass-if-parse connection "Content-Encoding" '(content-encoding))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue