Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(248)

Side by Side Diff: src/pkg/net/http/server.go

Issue 69260044: code review 69260044: net/http: add optional Server.ConnState callback (Closed)
Patch Set: diff -r 1424452d7eb5 https://go.googlecode.com/hg/ Created 11 years, 1 month ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pkg/net/http/serve_test.go ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // HTTP server. See RFC 2616. 5 // HTTP server. See RFC 2616.
6 6
7 package http 7 package http
8 8
9 import ( 9 import (
10 "bufio" 10 "bufio"
(...skipping 1061 matching lines...) Expand 10 before | Expand all | Expand 10 after
1072 // are blacklisted and can't be overridden with alternate 1072 // are blacklisted and can't be overridden with alternate
1073 // implementations. 1073 // implementations.
1074 func validNPN(proto string) bool { 1074 func validNPN(proto string) bool {
1075 switch proto { 1075 switch proto {
1076 case "", "http/1.1", "http/1.0": 1076 case "", "http/1.1", "http/1.0":
1077 return false 1077 return false
1078 } 1078 }
1079 return true 1079 return true
1080 } 1080 }
1081 1081
1082 func (c *conn) setState(nc net.Conn, state ConnectionState) {
1083 if hook := c.server.ClientConnState; hook != nil {
1084 hook(nc, state)
1085 }
1086 }
1087
1082 // Serve a new connection. 1088 // Serve a new connection.
1083 func (c *conn) serve() { 1089 func (c *conn) serve() {
1090 origConn := c.rwc // copy it before it's set nil on Close or Hijack
1091 c.setState(origConn, StateNew)
1084 defer func() { 1092 defer func() {
1085 if err := recover(); err != nil { 1093 if err := recover(); err != nil {
1086 const size = 64 << 10 1094 const size = 64 << 10
1087 buf := make([]byte, size) 1095 buf := make([]byte, size)
1088 buf = buf[:runtime.Stack(buf, false)] 1096 buf = buf[:runtime.Stack(buf, false)]
1089 log.Printf("http: panic serving %v: %v\n%s", c.remoteAdd r, err, buf) 1097 log.Printf("http: panic serving %v: %v\n%s", c.remoteAdd r, err, buf)
1090 } 1098 }
1091 if !c.hijacked() { 1099 if !c.hijacked() {
1092 c.close() 1100 c.close()
1101 c.setState(origConn, StateClosed)
1093 } 1102 }
1094 }() 1103 }()
1095 1104
1096 if tlsConn, ok := c.rwc.(*tls.Conn); ok { 1105 if tlsConn, ok := c.rwc.(*tls.Conn); ok {
1097 if d := c.server.ReadTimeout; d != 0 { 1106 if d := c.server.ReadTimeout; d != 0 {
1098 c.rwc.SetReadDeadline(time.Now().Add(d)) 1107 c.rwc.SetReadDeadline(time.Now().Add(d))
1099 } 1108 }
1100 if d := c.server.WriteTimeout; d != 0 { 1109 if d := c.server.WriteTimeout; d != 0 {
1101 c.rwc.SetWriteDeadline(time.Now().Add(d)) 1110 c.rwc.SetWriteDeadline(time.Now().Add(d))
1102 } 1111 }
1103 if err := tlsConn.Handshake(); err != nil { 1112 if err := tlsConn.Handshake(); err != nil {
1104 return 1113 return
1105 } 1114 }
1106 c.tlsState = new(tls.ConnectionState) 1115 c.tlsState = new(tls.ConnectionState)
1107 *c.tlsState = tlsConn.ConnectionState() 1116 *c.tlsState = tlsConn.ConnectionState()
1108 if proto := c.tlsState.NegotiatedProtocol; validNPN(proto) { 1117 if proto := c.tlsState.NegotiatedProtocol; validNPN(proto) {
1109 if fn := c.server.TLSNextProto[proto]; fn != nil { 1118 if fn := c.server.TLSNextProto[proto]; fn != nil {
1110 h := initNPNRequest{tlsConn, serverHandler{c.ser ver}} 1119 h := initNPNRequest{tlsConn, serverHandler{c.ser ver}}
1111 fn(c.server, tlsConn, h) 1120 fn(c.server, tlsConn, h)
1112 } 1121 }
1113 return 1122 return
1114 } 1123 }
1115 } 1124 }
1116 1125
1117 for { 1126 for {
1118 w, err := c.readRequest() 1127 w, err := c.readRequest()
1128 // TODO(bradfitz): could push this StateReading
1129 // earlier, but in practice header will be all in one
1130 // packet/Read:
1131 c.setState(c.rwc, StateReading)
1119 if err != nil { 1132 if err != nil {
1120 if err == errTooLarge { 1133 if err == errTooLarge {
1121 // Their HTTP client may or may not be 1134 // Their HTTP client may or may not be
1122 // able to read this if we're 1135 // able to read this if we're
1123 // responding to them and hanging up 1136 // responding to them and hanging up
1124 // while they're still writing their 1137 // while they're still writing their
1125 // request. Undefined behavior. 1138 // request. Undefined behavior.
1126 io.WriteString(c.rwc, "HTTP/1.1 413 Request Enti ty Too Large\r\n\r\n") 1139 io.WriteString(c.rwc, "HTTP/1.1 413 Request Enti ty Too Large\r\n\r\n")
1127 c.closeWriteAndWait() 1140 c.closeWriteAndWait()
1128 break 1141 break
(...skipping 25 matching lines...) Expand all
1154 break 1167 break
1155 } 1168 }
1156 1169
1157 // HTTP cannot have multiple simultaneous active requests.[*] 1170 // HTTP cannot have multiple simultaneous active requests.[*]
1158 // Until the server replies to this request, it can't read anoth er, 1171 // Until the server replies to this request, it can't read anoth er,
1159 // so we might as well run the handler in this goroutine. 1172 // so we might as well run the handler in this goroutine.
1160 // [*] Not strictly true: HTTP pipelining. We could let them al l process 1173 // [*] Not strictly true: HTTP pipelining. We could let them al l process
1161 // in parallel even if their responses need to be serialized. 1174 // in parallel even if their responses need to be serialized.
1162 serverHandler{c.server}.ServeHTTP(w, w.req) 1175 serverHandler{c.server}.ServeHTTP(w, w.req)
1163 if c.hijacked() { 1176 if c.hijacked() {
1177 c.setState(origConn, StateHijacked)
1164 return 1178 return
1165 } 1179 }
1166 w.finishRequest() 1180 w.finishRequest()
1167 if w.closeAfterReply { 1181 if w.closeAfterReply {
1168 if w.requestBodyLimitHit { 1182 if w.requestBodyLimitHit {
1169 c.closeWriteAndWait() 1183 c.closeWriteAndWait()
1170 } 1184 }
1171 break 1185 break
1172 } 1186 }
1187 c.setState(c.rwc, StateIdle)
1173 } 1188 }
1174 } 1189 }
1175 1190
1176 func (w *response) sendExpectationFailed() { 1191 func (w *response) sendExpectationFailed() {
1177 // TODO(bradfitz): let ServeHTTP handlers handle 1192 // TODO(bradfitz): let ServeHTTP handlers handle
1178 // requests with non-standard expectation[s]? Seems 1193 // requests with non-standard expectation[s]? Seems
1179 // theoretical at best, and doesn't fit into the 1194 // theoretical at best, and doesn't fit into the
1180 // current ServeHTTP model anyway. We'd need to 1195 // current ServeHTTP model anyway. We'd need to
1181 // make the ResponseWriter an optional 1196 // make the ResponseWriter an optional
1182 // "ExpectReplier" interface or something. 1197 // "ExpectReplier" interface or something.
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
1573 TLSConfig *tls.Config // optional TLS config, used by ListenAndSe rveTLS 1588 TLSConfig *tls.Config // optional TLS config, used by ListenAndSe rveTLS
1574 1589
1575 // TLSNextProto optionally specifies a function to take over 1590 // TLSNextProto optionally specifies a function to take over
1576 // ownership of the provided TLS connection when an NPN 1591 // ownership of the provided TLS connection when an NPN
1577 // protocol upgrade has occurred. The map key is the protocol 1592 // protocol upgrade has occurred. The map key is the protocol
1578 // name negotiated. The Handler argument should be used to 1593 // name negotiated. The Handler argument should be used to
1579 // handle HTTP requests and will initialize the Request's TLS 1594 // handle HTTP requests and will initialize the Request's TLS
1580 // and RemoteAddr if not already set. The connection is 1595 // and RemoteAddr if not already set. The connection is
1581 // automatically closed when the function returns. 1596 // automatically closed when the function returns.
1582 TLSNextProto map[string]func(*Server, *tls.Conn, Handler) 1597 TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
1598
1599 // ClientConnState optionally specifies a callback function
1600 // to note the state a connection is in.
1601 ClientConnState func(net.Conn, ConnectionState)
josharian 2014/02/26 23:07:56 Perhaps just ConnState? Not obvious to me what els
bradfitz 2014/02/26 23:16:43 I'm okay with that too, but there's also precedent
josharian 2014/02/26 23:41:57 Sorry, I was unclear. I was suggesting s/ClientCon
1602 }
1603
1604 // A ConnectionState represents the
josharian 2014/02/26 23:07:56 The second half of this comment is missing.
1605 type ConnectionState int
josharian 2014/02/26 23:07:56 Maybe just ConnState, to match net.Conn and Client
bradfitz 2014/02/26 23:16:43 See above.
1606
1607 const (
1608 // StateNew represents a new connection that is expected to
1609 // send a request immediately.
1610 StateNew ConnectionState = iota
1611
1612 // StateReading represent a connection that is reading its request.
josharian 2014/02/26 23:07:56 s/represent/represents/ s/.//
bradfitz 2014/02/26 23:16:43 Done.
1613 // and is about to be in a Handler.
1614 StateReading
1615
josharian 2014/02/26 23:07:56 Seems like there's a missing state here, StateHand
bradfitz 2014/02/26 23:16:43 I'd rather not introduce that. That's pretty much
1616 // StateIdle represents a connection that has finished a request
josharian 2014/02/26 23:07:56 s/finished a request/finished handling a request/
bradfitz 2014/02/26 23:16:43 Done.
1617 // and is in the keep-alive state, waiting for a new request.
1618 StateIdle
1619
1620 // StateHijacked occurs when a connection is hijacked.
1621 // This is a terminal state. It does not transition to
1622 // StateClose.
rcrowley 2014/02/27 01:44:08 s/StateClose/StateClosed/
1623 StateHijacked
1624
1625 // StateClosed occurs when a connection is closed.
1626 // Hijacked connections do not transition to StateClose.
rcrowley 2014/02/27 01:44:08 s/StateClose/StateClosed/
1627 StateClosed
1628 )
1629
1630 var stateName = map[ConnectionState]string{
1631 StateNew: "new",
1632 StateReading: "reading",
1633 StateIdle: "idle",
1634 StateHijacked: "hijacked",
1635 StateClosed: "closed",
1636 }
1637
1638 func (c ConnectionState) String() string {
1639 return stateName[c]
1583 } 1640 }
1584 1641
1585 // serverHandler delegates to either the server's Handler or 1642 // serverHandler delegates to either the server's Handler or
1586 // DefaultServeMux and also handles "OPTIONS *" requests. 1643 // DefaultServeMux and also handles "OPTIONS *" requests.
1587 type serverHandler struct { 1644 type serverHandler struct {
1588 srv *Server 1645 srv *Server
1589 } 1646 }
1590 1647
1591 func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) { 1648 func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
1592 handler := sh.srv.Handler 1649 handler := sh.srv.Handler
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
1937 log.Printf("%s.Read(%d) = %d, %v", c.name, len(p), n, err) 1994 log.Printf("%s.Read(%d) = %d, %v", c.name, len(p), n, err)
1938 return 1995 return
1939 } 1996 }
1940 1997
1941 func (c *loggingConn) Close() (err error) { 1998 func (c *loggingConn) Close() (err error) {
1942 log.Printf("%s.Close() = ...", c.name) 1999 log.Printf("%s.Close() = ...", c.name)
1943 err = c.Conn.Close() 2000 err = c.Conn.Close()
1944 log.Printf("%s.Close() = %v", c.name, err) 2001 log.Printf("%s.Close() = %v", c.name, err)
1945 return 2002 return
1946 } 2003 }
OLDNEW
« no previous file with comments | « src/pkg/net/http/serve_test.go ('k') | no next file » | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b