How to check if http.ResponseWriter has already closed a connection

4,600 views
Skip to first unread message

senior7515

unread,
Mar 19, 2012, 9:40:37 PM3/19/12
to golang-nuts
Hello,

Context: I'm playing with a very tiny muxer for http request
(bitbucket.org/agallego/plex). I want to check if an
http.ResponseWriter connection has been closed.

Question: How do I actually check that condition.

I tried to trace where it actually closes the connection or where it
checks, but couldn't find it.

I know that Response has a check (rather an exported variable)
http://weekly.golang.org/src/pkg/net/http/response.go?s=489:2256#L64

Any tips ?



Andrew Gerrand

unread,
Mar 20, 2012, 9:23:58 AM3/20/12
to senior7515, golang-nuts
My understanding that it is the responsibility of the dispatcher - the
thing that calls the Handler's ServeHTTP method - to close the
connection once the handler has returned.

If you are a muxer (which, I presume, also implements http.Handler),
you can presume that the handler is finished with the connection once
ServeHTTP returns. The connection itself won't be closed until your
muxer returns from its own ServeHTTP method and control is handed back
to the net/http's server functionality.

So it would seem your muxer can keep track of which connections are
open itself. Or perhaps I'm misunderstanding your question.

Andrew

Alexander Gallego

unread,
Mar 20, 2012, 8:06:30 PM3/20/12
to Andrew Gerrand, golang-nuts
I'm not sure I follow.

say func (w http.ResponseWriter, r *http.Request).

I want to do something like this:

if w.Close {
println("closed")
}


--- some thinkering -- further explaining ---
-- see file /net/http/server.go

Lets assume I have this

myFunc := func (w http.ResponseWriter, r *http.Request) {}

As I see it here is the call chain for ServeMux

lets assume it's called mux as in var mux ServeMux

mux.hanlder(r) --> returns a Hanlder --> which is in reality a
HandlerFunc with another level of indirection see line number 690 on
net/http/server.go

this then forwards the call to myFunc

I really see no explicit closing of the connections. even after
returning from ServeHTTP. See return statement line 924 on
/net/http/server.go

On 03/20/2012 09:23, Andrew Gerrand wrote:
> My understanding that it is the responsibility of the dispatcher - the
> thing that calls the Handler's ServeHTTP method - to close the
> connection once the handler has returned.

You mean that the muxer should call http.Request.Body.Close() ?

If this is true then the DefaultServeMux on the http package doesn't do
this.

> If you are a muxer (which, I presume, also implements http.Handler),

Yes.


> you can presume that the handler is finished with the connection once
> ServeHTTP returns.

How is this true? If this was true the default muxer on the http package
would close the connection
I don't think it does.

See line 918 of net/http/server.go

> The connection itself won't be closed until your
> muxer returns from its own ServeHTTP method and control is handed back
> to the net/http's server functionality.
>
> So it would seem your muxer can keep track of which connections are
> open itself. Or perhaps I'm misunderstanding your question.

to be honest, I'm may be confused. I still can't see how I can keep
track of the connections since http.ResponseWriter is an interface and I
don't have access to the *net.Conn

Thanks for the help.

Andrew Gerrand

unread,
Mar 20, 2012, 8:11:15 PM3/20/12
to Alexander Gallego, golang-nuts
You don't see the default muxer closing the connection because there
is an underlying mechanism to support keepalive, where multiple http
requests can be made using the same connection.

If you want your handler to close the connection explicitly, then you
can hijack the connection:

http://weekly.golang.org/pkg/net/http/#Hijacker (see the example)

What exactly are you trying to do?

Andrew

Alexander Gallego

unread,
Mar 20, 2012, 8:23:00 PM3/20/12
to Andrew Gerrand, golang-nuts

On 03/20/2012 20:11, Andrew Gerrand wrote:
> You don't see the default muxer closing the connection because there
> is an underlying mechanism to support keepalive, where multiple http
> requests can be made using the same connection.
>
> If you want your handler to close the connection explicitly, then you
> can hijack the connection:
>
> http://weekly.golang.org/pkg/net/http/#Hijacker (see the example)
>
> What exactly are you trying to do?

I mean quite literally I just want to find out if the connection for
ResponseWriter is closed.

Basically I have this use case

filter --> filter --> action --> filter filter. Pretty much what a
multiplexer is.

If a filter closes the connection I want to break out of the chain.
That's all.

Andrew Gerrand

unread,
Mar 20, 2012, 8:45:12 PM3/20/12
to Alexander Gallego, golang-nuts
On 21 March 2012 11:23, Alexander Gallego <galleg...@gmail.com> wrote:
>
>
> On 03/20/2012 20:11, Andrew Gerrand wrote:
>> You don't see the default muxer closing the connection because there
>> is an underlying mechanism to support keepalive, where multiple http
>> requests can be made using the same connection.
>>
>> If you want your handler to close the connection explicitly, then you
>> can hijack the connection:
>>
>> http://weekly.golang.org/pkg/net/http/#Hijacker (see the example)
>>
>> What exactly are you trying to do?
>
> I mean quite literally I just want to find out if the connection for
> ResponseWriter is closed.
>
> Basically I have this use case
>
> filter --> filter --> action --> filter filter. Pretty much what a
> multiplexer is.
>
> If a filter closes the connection I want to break out of the chain.
> That's all.

So are you talking about closing the Request.Body?

Because there's no Close method on an http.ResponseWriter.

Brad Fitzpatrick

unread,
Mar 20, 2012, 8:59:35 PM3/20/12
to Alexander Gallego, Andrew Gerrand, golang-nuts
On Tue, Mar 20, 2012 at 5:23 PM, Alexander Gallego <galleg...@gmail.com> wrote:


On 03/20/2012 20:11, Andrew Gerrand wrote:
> You don't see the default muxer closing the connection because there
> is an underlying mechanism to support keepalive, where multiple http
> requests can be made using the same connection.
>
> If you want your handler to close the connection explicitly, then you
> can hijack the connection:
>
> http://weekly.golang.org/pkg/net/http/#Hijacker (see the example)
>
> What exactly are you trying to do?

I mean quite literally I just want to find out if the connection for
ResponseWriter is closed.

Basically I have this use case

filter --> filter --> action --> filter filter. Pretty much what a
multiplexer is.

If a filter closes the connection I want to break out of the chain.
That's all.

Alexander Gallego

unread,
Mar 20, 2012, 9:40:36 PM3/20/12
to Andrew Gerrand, golang-nuts

On 03/20/2012 20:45, Andrew Gerrand wrote:
> On 21 March 2012 11:23, Alexander Gallego <galleg...@gmail.com> wrote:
>>
>> On 03/20/2012 20:11, Andrew Gerrand wrote:
>>> You don't see the default muxer closing the connection because there
>>> is an underlying mechanism to support keepalive, where multiple http
>>> requests can be made using the same connection.
>>>
>>> If you want your handler to close the connection explicitly, then you
>>> can hijack the connection:
>>>
>>> http://weekly.golang.org/pkg/net/http/#Hijacker (see the example)
>>>
>>> What exactly are you trying to do?
>> I mean quite literally I just want to find out if the connection for
>> ResponseWriter is closed.
>>
>> Basically I have this use case
>>
>> filter --> filter --> action --> filter filter. Pretty much what a
>> multiplexer is.
>>
>> If a filter closes the connection I want to break out of the chain.
>> That's all.
> So are you talking about closing the Request.Body?

No.

>
> Because there's no Close method on an http.ResponseWriter.

I know. this is why I originally asked.

In brief, you have a request and a response. (it's probably safe to
assume that they use the same tcp connection).

Say that the tcp connection that i'm writing *to* closes. (segfaults
..etc.. closed on the other end... etc..) I want to break out of my
chain of actions.

Alexander Gallego

unread,
Mar 20, 2012, 9:55:42 PM3/20/12
to Brad Fitzpatrick, Andrew Gerrand, golang-nuts
Thanks. correct me if I'm wrong, but does your CloseNotification()
function really work ? It only tells me when I'm done ServingHTTP(w, r)
Message has been deleted

Brad Fitzpatrick

unread,
Mar 20, 2012, 10:13:40 PM3/20/12
to Alexander Gallego, Andrew Gerrand, golang-nuts
On Tue, Mar 20, 2012 at 6:55 PM, Alexander Gallego <galleg...@gmail.com> wrote:
Thanks. correct me if I'm wrong, but does your CloseNotification()
function really work ? It only tells me when I'm done ServingHTTP(w, r)
 
Did you patch in 5453063? It passes its tests.

Alexander Gallego

unread,
Mar 20, 2012, 10:52:13 PM3/20/12
to Peter Thrun, golan...@googlegroups.com
I think that wouldn't work anyways. You can write headers multiple times.

Though the second time it will simply return (I tested this by letting
the connection timeout) successfully the first write returned 200ok and
when the hijacker tried to write something else it returned (from the
function) without writing again the same header. You can test yourself
with a simple hello world and gdb. just write something, let it time out
then step in and you'll notice.

I think that I still need to play around with my idea a bit more.
I can probably come up with a better question/problem/solution if I
allow time to hack around the /net pkg a little bit more.

On 03/20/2012 22:08, Peter Thrun wrote:
>> If a filter closes the connection I want to break out of the chain.
>> That's all
>>

> Have the filter return a value to indicate that it has completed the
> request and that no further processing is required. Alternatively, use
> some other object passed to the filters and actions to communicate the
> status of the request processing.
>
> If you do want to use the ResponseWriter, then wrap the response writer to
> keep track if WriteHeaders has been called or not.
>

Reply all
Reply to author
Forward
0 new messages