Roel Janssen <r...@gnu.org> writes:
> Amirouche Boubekki <amirou...@hypermove.net> writes: > >> On 2018-09-18 21:42, Roel Janssen wrote: >>> Dear Guilers, >>> >>> I'd like to implement a web server using the (web server) module, but >>> allow for “streaming” results. The way I imagine this would look like, >>> is something like this: >>> >>> (define (request-handler request body) >>> (values '((content-type . (text/plain))) >>> ;; This function can build its response by writing to >>> ;; ‘port’, rather than to return the whole body as a >>> ;; string. >>> (lambda (port) >>> (format port "Hello world!")))) >>> >>> (run-server request-handler) >>> >>> Is this possible with the (web server) module? If so, how? >> >> What you describe is exactly how it works. The second value can >> be a bytevector, #f or a procedure that takes a port as argument. >> >> Here is an example use [0] and here is the code [1] >> >> [0] >> https://framagit.org/a-guile-mind/culturia.next/blob/master/culturia/web/helpers.scm#L34 >> [1] >> https://git.savannah.gnu.org/cgit/guile.git/tree/module/web/server.scm#n198 >> >> Regards > > Thanks for your quick and elaborate reply! I didn't realize that in > writing the example I had written a working example. > > Looking at memory usage, it looks as if it puts all bytes produced by > that function into memory at once before sending the HTTP response over > the network. Is that observation correct? If so, can it be avoided? As an addition to the above, here's an example implementation: (use-modules (web server) (web request) (web response) (web http) (ice-9 receive) (ice-9 rdelim)) (define (process-input input-port output-port) (unless (or (port-closed? input-port) (port-closed? output-port)) (let ((line (read-line input-port))) (if (eof-object? line) (begin (close-port input-port) #t) (begin (format output-port "~a~%" line) (process-input input-port output-port)))))) (define (request-handler request body) (values '((content-type . (text/plain)) (transfer-encoding . ((chunked)))) (lambda (port) (call-with-input-file "large-file.txt" (lambda (input-port) (process-input input-port port)))))) (run-server request-handler) In the example, “large-file.txt” is a file of a few gigabytes, and the Guile process grows to a few gigabytes as well. Kind regards, Roel Janssen