gocraft / web

Go Router + Middleware. Your Contexts.
MIT License
1.51k stars 124 forks source link

Trouble with web.ResponseWriter.Flush() #31

Closed kofalt closed 10 years ago

kofalt commented 10 years ago

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.

kofalt commented 10 years ago

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 :)

cypriss commented 10 years ago

@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.

kofalt commented 10 years ago

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?

cypriss commented 10 years ago

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

kofalt commented 10 years ago

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 :)