gocraft / web

Go Router + Middleware. Your Contexts.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Trouble with web.ResponseWriter.Flush()

kofalt opened this issue · comments

Using a trivially modified example that sleeps in the middle of an output:

func (c *Context) SayHello(rw web.ResponseWriter, req *web.Request) {
    Fprint(rw, strings.Repeat("Hello ", c.HelloCount), "World!")

    rw.Flush()
    time.Sleep(2 * time.Second)

    Fprint(rw, strings.Repeat("Hello ", c.HelloCount), "World!")
}

Running curl 127.0.0.1:3000 won't print anything until the entire output is finished.
Adding a newline to the printed strings will make this example behave as expected.

Is this an issue with gocraft/web, or is the problem at another layer?
Do you forsee any issues with leaving requests open like this?

I'm assuming that each request is inside its own gofunc, and so could be used to trivially implement server-sent events, an alternative to websockets that uses "plain" HTTP.

Oops: I didn't think far enough ahead to try my example with a browser; it looks like the newline issue is curl's fault, not gocraft/web's. In Firefox, the above example works unmodified.

If you could answer the second question Re: long-running requests we can close this out :)

@kofalt to be honest I think this could be used to implement an SSE-type of thing, but I've never done it. There's also packages like this for SSE: https://github.com/antage/eventsource. It would be pretty easy to use that with gocraft/web with a small wrapper.

Hmm, fair enough. I did notice that when I modified my example thus:

func (c *Context) SayHello(rw web.ResponseWriter, req *web.Request) {
    Println("Running handler")

    for n := 1; n < 10; n++ {
        Fprint(rw, strings.Repeat("Hello ", c.HelloCount), "World!\n")
        rw.Flush()
        time.Sleep(1 * time.Second)
    }
    Fprint(rw, strings.Repeat("Hello ", c.HelloCount), "World!\n")
}

And made multiple requests at the same time, each would block until the previous request had finished. The Running handler messages only printed one at a time also.

This gives the appearance of gocraft/web only handling one request at a time; thoughts?

@kofalt I think Firefox only sends 1 request at a time. Try using firefox + chrome.

You're absolutely right. How embarassing. This appears to be unaffected by Firefox's network.http.max-connections-per-server setting (possibly because it's the same URL).

Notably, Chrome won't print any output until the mesage is done, so instead by using Firefox & curl, or multiple runs of curl, the correct behavior can be observed.

Thanks for your help getting started :)