guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 03/06: web: Don't hide missing data in the chunked input


From: Ludovic Courtès
Subject: [Guile-commits] 03/06: web: Don't hide missing data in the chunked input port.
Date: Mon, 4 Jul 2022 05:52:40 -0400 (EDT)

civodul pushed a commit to branch main
in repository guile.

commit baa14243355b8a4a7f5228d347ad3ff7057e7312
Author: Christopher Baines <mail@cbaines.net>
AuthorDate: Thu Jun 30 19:15:54 2022 +0100

    web: Don't hide missing data in the chunked input port.
    
    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.
    
    Signed-off-by: Ludovic Courtès <ludo@gnu.org>
---
 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 827adad3e..29736f2eb 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
 
@@ -1945,6 +1948,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."
@@ -1997,8 +2011,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 3c2acf11c..06dd9479c 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 ()
@@ -491,6 +494,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)



reply via email to

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