diff options
Diffstat (limited to 'src/pkg/net/http/server.go')
| -rw-r--r-- | src/pkg/net/http/server.go | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/pkg/net/http/server.go b/src/pkg/net/http/server.go index fea1898fd7..8ca48ab3ce 100644 --- a/src/pkg/net/http/server.go +++ b/src/pkg/net/http/server.go @@ -1079,8 +1079,16 @@ func validNPN(proto string) bool { return true } +func (c *conn) setState(nc net.Conn, state ConnState) { + if hook := c.server.ConnState; hook != nil { + hook(nc, state) + } +} + // Serve a new connection. func (c *conn) serve() { + origConn := c.rwc // copy it before it's set nil on Close or Hijack + c.setState(origConn, StateNew) defer func() { if err := recover(); err != nil { const size = 64 << 10 @@ -1090,6 +1098,7 @@ func (c *conn) serve() { } if !c.hijacked() { c.close() + c.setState(origConn, StateClosed) } }() @@ -1116,6 +1125,10 @@ func (c *conn) serve() { for { w, err := c.readRequest() + // TODO(bradfitz): could push this StateActive + // earlier, but in practice header will be all in one + // packet/Read: + c.setState(c.rwc, StateActive) if err != nil { if err == errTooLarge { // Their HTTP client may or may not be @@ -1161,6 +1174,7 @@ func (c *conn) serve() { // in parallel even if their responses need to be serialized. serverHandler{c.server}.ServeHTTP(w, w.req) if c.hijacked() { + c.setState(origConn, StateHijacked) return } w.finishRequest() @@ -1170,6 +1184,7 @@ func (c *conn) serve() { } break } + c.setState(c.rwc, StateIdle) } } @@ -1580,6 +1595,58 @@ type Server struct { // and RemoteAddr if not already set. The connection is // automatically closed when the function returns. TLSNextProto map[string]func(*Server, *tls.Conn, Handler) + + // ConnState specifies an optional callback function that is + // called when a client connection changes state. See the + // ConnState type and associated constants for details. + ConnState func(net.Conn, ConnState) +} + +// A ConnState represents the state of a client connection to a server. +// It's used by the optional Server.ConnState hook. +type ConnState int + +const ( + // StateNew represents a new connection that is expected to + // send a request immediately. Connections begin at this + // state and then transition to either StateActive or + // StateClosed. + StateNew ConnState = iota + + // StateActive represents a connection that has read 1 or more + // bytes of a request. The Server.ConnState hook for + // StateActive fires before the request has entered a handler + // and doesn't fire again until the request has been + // handled. After the request is handled, the state + // transitions to StateClosed, StateHijacked, or StateIdle. + StateActive + + // StateIdle represents a connection that has finished + // handling a request and is in the keep-alive state, waiting + // for a new request. Connections transition from StateIdle + // to either StateActive or StateClosed. + StateIdle + + // StateHijacked represents a hijacked connection. + // This is a terminal state. It does not transition to StateClosed. + StateHijacked + + // StateClosed represents a closed connection. + // This is a terminal state. Hijacked connections do not + // transition to StateClosed. + StateClosed +) + +var stateName = map[ConnState]string{ + StateNew: "new", + StateActive: "active", + StateIdle: "idle", + StateHijacked: "hijacked", + StateClosed: "closed", +} + +func (c ConnState) String() string { + return stateName[c] } // serverHandler delegates to either the server's Handler or |
