guile-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]