guix_mirror_bot pushed a commit to branch master
in repository guix.

commit 0c5108766ffbd3ae0e6801a9b05694362df789dd
Author: Ludovic Courtès <[email protected]>
AuthorDate: Tue Sep 8 15:20:52 2026 +0200

    publish: Use chunked encoding when size is unknown.
    
    * guix/scripts/publish.scm (render-nar): Add ‘Transfer-Encoding’ header.
    (nar-compressed-port): Use ‘make-zlib-output-port’ instead of
    ‘make-gzip-output-port’.
    (http-write)[chunk-size]: New variable.
    In ‘application/x–nix-archive’ case, call ‘make-chunked-output-port’ instead
    of ‘duplicate-port’.
    * tests/publish.scm ("/nar/gzip/*"): Change to ‘call-with-zlib-input-port’.
    ("/nar/gzip/* is really gzip"): Adjust comment accordingly.
    
    Fixes: guix/guix#10190
    Reported-by: Vagrant Cascadian <[email protected]>
    Suggested-by: Christopher Baines <[email protected]>
    Signed-off-by: Ludovic Courtès <[email protected]>
    Merges: #11131
---
 guix/scripts/publish.scm | 20 +++++++++++++++-----
 tests/publish.scm        | 12 ++++++------
 2 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/guix/scripts/publish.scm b/guix/scripts/publish.scm
index 6f213234e35..3f0087ff6c2 100644
--- a/guix/scripts/publish.scm
+++ b/guix/scripts/publish.scm
@@ -708,6 +708,11 @@ requested using POOL."
     (if (valid-path? store store-path)
         (values `((content-type . (application/x-nix-archive
                                    (charset . "ISO-8859-1")))
+
+                  ;; Since the size is unknown, 'Content-Length' cannot be
+                  ;; provided so we have to fall back to chunked encoding.
+                  (transfer-encoding . ((chunked)))
+
                   (x-nar-compression . ,compression))
                 ;; XXX: We're not returning the actual contents, deferring
                 ;; instead to 'http-write'.  This is a hack to work around
@@ -897,9 +902,8 @@ EXP..."
 according to COMPRESSION."
   (match compression
     (($ <compression> 'gzip level)
-     ;; Note: We cannot used chunked encoding here because
-     ;; 'make-gzip-output-port' wants a file port.
-     (make-gzip-output-port port
+     (make-zlib-output-port port
+                            #:format 'gzip
                             #:level level
                             #:buffer-size %default-buffer-size))
     (($ <compression> 'lzip level)
@@ -950,6 +954,10 @@ blocking."
     (force-output port)
     (poll-set-add! (http-poll-set server) port *events*))
 
+  (define chunk-size
+    ;; Size in bytes of chunks for chunked transfer encoding.
+    (expt 2 17))
+
   (define compression
     (assoc-ref (response-headers response) 'x-nar-compression))
 
@@ -979,8 +987,10 @@ blocking."
                                 ;; returned port.  This is needed for the
                                 ;; keep-alive mechanism.
                                 (nar-compressed-port
-                                 (duplicate-port
-                                  (response-port response) "w+0b")
+                                 (make-chunked-output-port
+                                  (response-port response)
+                                  #:keep-alive? keep-alive?
+                                  #:buffering chunk-size)
                                  compression))))
             ;; XXX: Given our ugly workaround for <http://bugs.gnu.org/21093>
             ;; in 'render-nar', BODY here is just the file name of the store
diff --git a/tests/publish.scm b/tests/publish.scm
index 91576abf139..47a60e7580e 100644
--- a/tests/publish.scm
+++ b/tests/publish.scm
@@ -1,7 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015 David Thompson <[email protected]>
 ;;; Copyright © 2020 by Amar M. Singh <[email protected]>
-;;; Copyright © 2016-2022, 2024 Ludovic Courtès <[email protected]>
+;;; Copyright © 2016-2022, 2024, 2026 Ludovic Courtès <[email protected]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -262,15 +262,15 @@ FileSize: ~a~%"
      (let ((nar (http-get-port
                  (publish-uri
                   (string-append "/nar/gzip/" (basename %item))))))
-       (call-with-gzip-input-port nar
-         (cut restore-file <> temp)))
+       (call-with-zlib-input-port nar
+         (cut restore-file <> temp)
+         #:format 'gzip))
      (call-with-input-file temp read-string))))
 
 (test-equal "/nar/gzip/* is really gzip"
   %gzip-magic-bytes
-  ;; Since 'gzdopen' (aka. 'call-with-gzip-input-port') transparently reads
-  ;; uncompressed gzip, the test above doesn't check whether it's actually
-  ;; gzip.  This is what this test does.  See <https://bugs.gnu.org/30184>.
+  ;; Explicitly check whether it's actually gzip.
+  ;; See <https://bugs.gnu.org/30184>.
   (let ((nar (http-get-port
               (publish-uri
                (string-append "/nar/gzip/" (basename %item))))))

Reply via email to