From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Christopher Baines Newsgroups: gmane.lisp.guile.devel Subject: [PATCH] web: Support reading chunked request bodies. Date: Thu, 20 Jul 2023 15:02:38 +0100 Message-ID: <20230720140240.23588-1-mail@cbaines.net> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="35017"; mail-complaints-to="usenet@ciao.gmane.io" To: guile-devel@gnu.org Original-X-From: guile-devel-bounces+guile-devel=m.gmane-mx.org@gnu.org Thu Jul 20 16:03:04 2023 Return-path: Envelope-to: guile-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qMUFC-0008uZ-MS for guile-devel@m.gmane-mx.org; Thu, 20 Jul 2023 16:03:02 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qMUEz-0002fq-0X; Thu, 20 Jul 2023 10:02:50 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qMUEt-0002cb-Hw for guile-devel@gnu.org; Thu, 20 Jul 2023 10:02:43 -0400 Original-Received: from mira.cbaines.net ([212.71.252.8]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qMUEs-0005vR-1K for guile-devel@gnu.org; Thu, 20 Jul 2023 10:02:43 -0400 Original-Received: from localhost (unknown [IPv6:2a02:8010:68c1:0:54d1:d5d4:280e:f699]) by mira.cbaines.net (Postfix) with ESMTPSA id A13D227BBE2 for ; Thu, 20 Jul 2023 15:02:40 +0100 (BST) Original-Received: from localhost (localhost [local]) by localhost (OpenSMTPD) with ESMTPA id 30483633 for ; Thu, 20 Jul 2023 14:02:40 +0000 (UTC) X-Mailer: git-send-email 2.41.0 Received-SPF: pass client-ip=212.71.252.8; envelope-from=mail@cbaines.net; helo=mira.cbaines.net X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-devel-bounces+guile-devel=m.gmane-mx.org@gnu.org Original-Sender: guile-devel-bounces+guile-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.lisp.guile.devel:21903 Archived-At: Guile already supports chunked response bodies, but chunked request bodies are allowed as well. This is useful when you're sending an unknown amount of data in the request. * module/web/request.scm (read-request-body): Support the request body being chunked. --- module/web/request.scm | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/module/web/request.scm b/module/web/request.scm index ff4b94485..b24bc0d77 100644 --- a/module/web/request.scm +++ b/module/web/request.scm @@ -221,15 +221,23 @@ on PORT, perhaps using some transfer encoding." (request-headers r) (request-meta r) port))) (define (read-request-body r) - "Reads the request body from R, as a bytevector. Return ‘#f’ -if there was no request body." - (let ((nbytes (request-content-length r))) - (and nbytes - (let ((bv (get-bytevector-n (request-port r) nbytes))) - (if (= (bytevector-length bv) nbytes) - bv - (bad-request "EOF while reading request body: ~a bytes of ~a" - (bytevector-length bv) nbytes)))))) + "Reads the request body from R. If the request body is chunked, a port +will be returned. Otherwise, if the request body is present, it will be +returned as a bytevector or ‘#f’ will be returned if there was no +request body." + (cond + ((member '(chunked) (request-transfer-encoding r)) + (make-chunked-input-port (request-port r) + ;; closing the port is handled elsewhere + #:keep-alive? #t)) + (else + (let ((nbytes (request-content-length r))) + (and nbytes + (let ((bv (get-bytevector-n (request-port r) nbytes))) + (if (= (bytevector-length bv) nbytes) + bv + (bad-request "EOF while reading request body: ~a bytes of ~a" + (bytevector-length bv) nbytes)))))))) (define (write-request-body r bv) "Write BV, a bytevector, to the port corresponding to the HTTP -- 2.41.0