net/http: Close connection when client closes connection (CloseNotify)

1,355 views
Skip to first unread message

champetie...@gmail.com

unread,
Dec 5, 2014, 12:15:44 PM12/5/14
to golan...@googlegroups.com
Hi,

I would like to finish closing the tcp connection when i detect (with CloseNotify()) that the client has closed the connection.
I've tried hijacking it but it's forbidden (http: Hijack is incompatible with use of CloseNotifier)

here a small test case:
package main

import (
       
"log"
       
"time"
       
"net/http"
)

func handler
(w http.ResponseWriter, r *http.Request) {
        log
.Print("start")
       
select {
       
case <-time.After(time.Duration(10) * time.Second):
                log
.Print("OK")
                w
.Write([]byte("Hi"))
       
case <-w.(http.CloseNotifier).CloseNotify():
                log
.Print("KO: Connection closed")
               
//http.Error(w, "Client Closed Request", 499)
       
}
}

func main
() {
        http
.HandleFunc("/", handler)
        http
.ListenAndServe(":8080", nil)
}


Run this, start wireshark, navigate to http://127.0.0.1:8080 with firefox, and cancel the request.
You will see: (c = client, s= server)
c->s SYN
s->c SYN-ACK
c->s ACK
c->s GET / HTTP/1.1
s->c ACK
c->s FIN-ACK
s->c HTTP/1.1 200 OK (we send a response even if the client already close his connection ...)
c->s RST

So how can i stop responding to this client?
(for now i'm using the commented line)

Thanks in advance
Etienne

James Bardin

unread,
Dec 5, 2014, 2:10:16 PM12/5/14
to golan...@googlegroups.com, champetie...@gmail.com


On Friday, December 5, 2014 12:15:44 PM UTC-5, champetie...@gmail.com wrote:

So how can i stop responding to this client?
(for now i'm using the commented line)



I don't think there's a way right now to stop it from sending a minimal response packet. It looks like it should be fixable, but it shouldn't affect much as is.
Is it actually causing a problem for you?

champetie...@gmail.com

unread,
Dec 8, 2014, 4:40:10 AM12/8/14
to golan...@googlegroups.com, champetie...@gmail.com

Thanks for your answer.
It's not causing real problem,
I just had an hard time understanding why the hell go is responding 200 OK when the client close the connection ... (and why is it responding at all)

Tommi Virtanen

unread,
Dec 11, 2014, 1:49:17 PM12/11/14
to golan...@googlegroups.com, champetie...@gmail.com
On Monday, December 8, 2014 1:40:10 AM UTC-8, champetie...@gmail.com wrote:
Thanks for your answer.
It's not causing real problem,
I just had an hard time understanding why the hell go is responding 200 OK when the client close the connection ... (and why is it responding at all)

Consider the case where the client is talking HTTP/1.0 without Connection: keep-alive. 

James Bardin

unread,
Dec 11, 2014, 2:09:26 PM12/11/14
to Tommi Virtanen, golan...@googlegroups.com, champetie...@gmail.com

On Thu, Dec 11, 2014 at 1:49 PM, Tommi Virtanen <tommi.v...@gmail.com> wrote:
Consider the case where the client is talking HTTP/1.0 without Connection: keep-alive. 
 

Consider what exactly?

The connection is half-closed, and the packet is sent because the part of the server that send the response isn't notified about the close being initiated.

Tommi Virtanen

unread,
Dec 11, 2014, 3:35:15 PM12/11/14
to golan...@googlegroups.com, tommi.v...@gmail.com, champetie...@gmail.com
On Thursday, December 11, 2014 11:09:26 AM UTC-8, James Bardin wrote:
Consider the case where the client is talking HTTP/1.0 without Connection: keep-alive. 

Consider what exactly?

The connection is half-closed, and the packet is sent because the part of the server that send the response isn't notified about the close being initiated.

The incoming stream half-closing doesn't necessarily mean the HTTP conversation is over. It seems risky for net/http to assume that, and would need protocol level checks around it to stay HTTP/1.0 compliant.

The server side connection will sit in LAST_ACK anyway until it gets a response back. That response might as well be the RST sending a HTTP response triggers on aborted clients.

James Bardin

unread,
Dec 11, 2014, 3:48:55 PM12/11/14
to Tommi Virtanen, golan...@googlegroups.com, champetie...@gmail.com
On Thu, Dec 11, 2014 at 3:35 PM, Tommi Virtanen <tommi.v...@gmail.com> wrote:
The incoming stream half-closing doesn't necessarily mean the HTTP conversation is over. It seems risky for net/http to assume that, and would need protocol level checks around it to stay HTTP/1.0 compliant.


I'm just curious if I'm forgetting something. The server has received at least a FIN at this point, what part of the protocol would be violated by swallowing the response? (I'm not saying this needs to be fixed, just playing devil's advocate)

 
The server side connection will sit in LAST_ACK anyway until it gets a response back. That response might as well be the RST sending a HTTP response triggers on aborted clients.

True, which is why I figured it wasn't worth fixing. It's probably not worth the extra code to check for a close at that point, especially since it's a race anyway and there could already be a FIN in flight.

Tommi Virtanen

unread,
Dec 11, 2014, 4:04:05 PM12/11/14
to golan...@googlegroups.com, tommi.v...@gmail.com, champetie...@gmail.com
On Thursday, December 11, 2014 12:48:55 PM UTC-8, James Bardin wrote:
The incoming stream half-closing doesn't necessarily mean the HTTP conversation is over. It seems risky for net/http to assume that, and would need protocol level checks around it to stay HTTP/1.0 compliant.
I'm just curious if I'm forgetting something. The server has received at least a FIN at this point, what part of the protocol would be violated by swallowing the response? (I'm not saying this needs to be fixed, just playing devil's advocate)

RFC1945 did require a Content-Length header for all requests with a body, but that wasn't followed very well. There are (hopefully never run anymore) HTTP/1.0 clients that did not use any of Content-Length: ..., Connection: keepalive, or Transfer-Encoding: chunked. They would signal end of the request body by a half-close. Ugly? Yes. Likely to cause corruption? Very much so. The world is a better place now, but sending that response is marginally better than not sending it; let RST happen if it was a real close and not a half-close.

Remember, net/http really doesn't know whether your handler decided to abort or not, so you really want to set an error status, if for no other reason than being wrapped by some middleware that will otherwise think your handler was successful.

James Bardin

unread,
Dec 11, 2014, 4:20:34 PM12/11/14
to golan...@googlegroups.com, tommi.v...@gmail.com, champetie...@gmail.com


On Thursday, December 11, 2014 4:04:05 PM UTC-5, Tommi Virtanen wrote:
On Thursday, December 11, 2014 12:48:55 PM UTC-8, James Bardin wrote:
The incoming stream half-closing doesn't necessarily mean the HTTP conversation is over. It seems risky for net/http to assume that, and would need protocol level checks around it to stay HTTP/1.0 compliant.
I'm just curious if I'm forgetting something. The server has received at least a FIN at this point, what part of the protocol would be violated by swallowing the response? (I'm not saying this needs to be fixed, just playing devil's advocate)

RFC1945 did require a Content-Length header for all requests with a body, but that wasn't followed very well. There are (hopefully never run anymore) HTTP/1.0 clients that did not use any of Content-Length: ..., Connection: keepalive, or Transfer-Encoding: chunked. They would signal end of the request body by a half-close. Ugly? Yes. Likely to cause corruption? Very much so. The world is a better place now, but sending that response is marginally better than not sending it; let RST happen if it was a real close and not a half-close.


A half-closed client, that's what I wasn't thinking of! ;)
 
Reply all
Reply to author
Forward
0 new messages