
AFAICT by reading its source, the web-server lib seems to support streaming, but I can’t get it to work. My request handler looks like this:
(define ((get-current-visitors cv) req)
(response/output
(lambda (out)
(current-visitors-subscribe cv (current-thread))
(let loop ()
(write-bytes (string->bytes/utf-8 (number->string (thread-receive))) out)
(flush-output out)
(unless (port-closed? out)
(loop))))))
Am I doing something obviously wrong here?

Requests stall until they time out and that’s when they finally print all the output at once.

I thought it might be a buffering issue which is why I threw that flush-output
in there but I don’t think it should be necessary.

Output from curl:
$ curl -v <http://localhost:8000/v0/visitors>
* Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 8000 failed: Connection refused
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET /v0/visitors HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.54.0
> Accept: */*
>
* 60 seconds pass here *
< HTTP/1.1 200 Okay
< Date: Fri, 09 Nov 2018 16:51:59 GMT
< Last-Modified: Fri, 09 Nov 2018 16:51:59 GMT
< Server: Racket
< Content-Type: text/html; charset=utf-8
< Transfer-Encoding: chunked
<
* transfer closed with outstanding read data remaining
* stopped the pause stream!
* Closing connection 0
curl: (18) transfer closed with outstanding read data remaining
00000000000000000000000000000000000000000000000000000000000

You’re assuming the port will be closed at some iteration of the loop, but it’s not clear why.

The browser closes the connection (i.e. the user closes a tab or something)

It’s not clear from the curl output, but the response really only starts after about 60s, which is when curl seems to time out the request.

Is it possible curl
itself is buffering the output?

I don’t think so. The response headers aren’t returned until curl closes the connection either, from what I can tell.

Yeah, it looks like the server doesn’t even return the response headers immediately even though it should:
$ telnet 127.1 8000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET /v0/visitors HTTP/1.1
Host: localhost
*nothing gets returned here*

Okay, I think there is some buffering going on inside the web server after all. If I append 4096 “a”’s to my output then the response gets streamed out.

https://github.com/racket/web-server/blob/master/web-server-lib/web-server/http/response.rkt#L111 looks like my handler is writing to a pipe, which, according to the docs, should not be buffered.

So I guess the data is being buffered on the OS socket, since the chunking loop (https://github.com/racket/web-server/blob/master/web-server-lib/web-server/http/response.rkt#L119) doesn’t explicitly flush after every chunk.

Yeah, patching that loop to (flush-output to-child)
after every iteration fixes the problem.
