From 6b6aef2192769ce12a2962b02d103a019f4bc9c6 Mon Sep 17 00:00:00 2001 From: NalaGinrut Date: Sun, 11 Mar 2012 23:02:07 +0800 Subject: [PATCH] read-response-body should return received data in any break --- module/web/response.scm | 52 +++++++++++++++++++++++++++++++++++++++------- 1 files changed, 44 insertions(+), 8 deletions(-) diff --git a/module/web/response.scm b/module/web/response.scm index 07e1245..e3ea0a6 100644 --- a/module/web/response.scm +++ b/module/web/response.scm @@ -21,6 +21,7 @@ (define-module (web response) #:use-module (rnrs bytevectors) + #:autoload (rnrs) (call-with-port) #:use-module (ice-9 binary-ports) #:use-module (ice-9 rdelim) #:use-module (srfi srfi-9) @@ -38,6 +39,8 @@ response-must-not-include-body? read-response-body + output-received-response-body + throw-from-response-body-break write-response-body ;; General headers @@ -224,16 +227,49 @@ This is true for some response types, like those with code 304." (= (response-code r) 204) (= (response-code r) 304))) -(define (read-response-body r) +(define* (read-response-body r #:key (block 4096)) "Reads the response body from @var{r}, as a bytevector. Returns @code{#f} if there was no response body." - (let ((nbytes (response-content-length r))) - (and nbytes - (let ((bv (get-bytevector-n (response-port r) nbytes))) - (if (= (bytevector-length bv) nbytes) - bv - (bad-response "EOF while reading response body: ~a bytes of ~a" - (bytevector-length bv) nbytes)))))) + (let* ((nbytes (response-content-length r)) + (bv (and nbytes (make-bytevector nbytes))) + (start 0)) + (catch #t + (lambda () + (let lp((buf (get-bytevector-n (response-port r) block))) + (if (eof-object? buf) + bv + (let ((len (bytevector-length buf))) + (cond + ((<= len block) + (bytevector-copy! buf 0 bv start len) + (set! start (+ start len)) + (lp (get-bytevector-n (response-port r) block))) + (else + (bad-response "EOF while reading response body: ~a bytes of ~a" + start nbytes))))))) + (lambda (k . e) + (let ((received (call-with-port + (open-bytevector-input-port bv) + (lambda (port) + (get-bytevector-n port start))))) + (throw k `(,@e (body ,@received))) ;; return the received data + ))))) + +;; output the received data if there is, or do nothing +(define (output-received-response-body e port) + (let ((received (assoc-ref (cadr e) 'body))) + (if received + (begin + (put-bytevector port received) + (force-output port))))) + +;; Exceptional information contains the received bytevector added from the +;; read-response-body if any exception had been caught. +;; If received data ware huge(it always does), it'd be a trouble during the tracing. +;; This helper function could get rid of the received data from exceptional info, +;; and re-throw it. +(define (throw-from-response-body-break e) + (throw (car e) (list-head (cdr e) (1- (length (cdr e)))))) (define (write-response-body r bv) "Write @var{bv}, a bytevector, to the port corresponding to the HTTP -- 1.7.0.4