[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/2] web: Don't hide missing data in the chunked input port.
From: |
Christopher Baines |
Subject: |
[PATCH 2/2] web: Don't hide missing data in the chunked input port. |
Date: |
Thu, 30 Jun 2022 19:15:54 +0100 |
This port is of limited use if it cannot be used reliably. Rather than
behaving as if the input has finished when it ends unexpectedly, instead
raise an exception.
* module/web/http.scm (make-chunked-input-port): Raise an exception on
premature termination.
(&chunked-input-ended-prematurely): New exception type.
(chunked-input-ended-prematurely-error?): New procedure.
* test-suite/tests/web-http.test (pass-if-named-exception): Rename to
pass-if-named-exception.
(pass-if-named-exception): New syntax.
("Exception on premature chunk end"): New test for this behaviour.
---
doc/ref/web.texi | 3 +++
module/web/http.scm | 18 ++++++++++++++++--
test-suite/tests/web-http.test | 25 +++++++++++++++++--------
3 files changed, 36 insertions(+), 10 deletions(-)
diff --git a/doc/ref/web.texi b/doc/ref/web.texi
index 93cd0214f..b04d328b7 100644
--- a/doc/ref/web.texi
+++ b/doc/ref/web.texi
@@ -1117,6 +1117,9 @@ Returns a new port, that transparently reads and decodes
chunk-encoded
data from @var{port}. If no more chunk-encoded data is available, it
returns the end-of-file object. When the port is closed, @var{port} will
also be closed, unless @var{keep-alive?} is true.
+
+If the chunked input ends prematurely, a
+@code{&chunked-input-ended-promaturely} exception will be raised.
@end deffn
@example
diff --git a/module/web/http.scm b/module/web/http.scm
index 163c52176..b3ea076ae 100644
--- a/module/web/http.scm
+++ b/module/web/http.scm
@@ -38,6 +38,7 @@
#:use-module (ice-9 q)
#:use-module (ice-9 binary-ports)
#:use-module (ice-9 textual-ports)
+ #:use-module (ice-9 exceptions)
#:use-module (rnrs bytevectors)
#:use-module (web uri)
#:export (string->header
@@ -67,6 +68,8 @@
read-response-line
write-response-line
+ &chunked-input-error-prematurely
+ chunked-input-ended-prematurely-error?
make-chunked-input-port
make-chunked-output-port
@@ -1935,6 +1938,17 @@ treated specially, and is just returned as a plain
string."
;; Chunked Responses
+(define &chunked-input-ended-prematurely
+ (make-exception-type '&chunked-input-error-prematurely
+ &external-error
+ '()))
+
+(define make-chunked-input-ended-prematurely-error
+ (record-constructor &chunked-input-ended-prematurely))
+
+(define chunked-input-ended-prematurely-error?
+ (record-predicate &chunked-input-ended-prematurely))
+
(define (read-chunk-header port)
"Read a chunk header from PORT and return the size in bytes of the
upcoming chunk."
@@ -1987,8 +2001,8 @@ closed it will also close PORT, unless the KEEP-ALIVE? is
true."
ask-for)))
(cond
((eof-object? read) ;premature termination
- (set! finished? #t)
- num-read)
+ (raise-exception
+ (make-chunked-input-ended-prematurely-error)))
(else
(let ((left (- remaining read)))
(set! remaining left)
diff --git a/test-suite/tests/web-http.test b/test-suite/tests/web-http.test
index 86fbc0e1a..796c44dd9 100644
--- a/test-suite/tests/web-http.test
+++ b/test-suite/tests/web-http.test
@@ -28,16 +28,19 @@
#:use-module (test-suite lib))
-(define-syntax pass-if-named-exception
+(define-syntax pass-if-expected-exception
(syntax-rules ()
- ((_ name k pat exp)
+ ((_ name exception-predicate? exp)
(pass-if name
- (catch 'k
- (lambda () exp (error "expected exception" 'k))
- (lambda (k message args)
- (if (string-match pat message)
- #t
- (error "unexpected exception" message args))))))))
+ (with-exception-handler
+ (lambda (exn)
+ (if (exception-predicate? exn)
+ #t
+ (error "unexpected exception" exn)))
+ (lambda ()
+ exp
+ #f)
+ #:unwind? #t)))))
(define-syntax pass-if-only-parse
(syntax-rules ()
@@ -486,6 +489,12 @@
(port (make-chunked-input-port (open-input-string str))))
(get-string-all port)))
+ (pass-if-expected-exception "Exception on premature chunk end"
+ chunked-input-ended-prematurely-error?
+ (let* ((str "b\r\nFirst chunk\r\nc\r\nSecond chun")
+ (port (make-chunked-input-port (open-input-string str))))
+ (get-string-all port)))
+
(pass-if-equal
(call-with-output-string
(lambda (out-raw)
--
2.36.1