Skip to content

Commit 8aacbec

Browse files
committed
http2: with Go 1.7 set Request.Context in ServeHTTP handlers
And act the same as HTTP/1.x in Go 1.7. Updates golang/go#15134 Change-Id: Ib64dd82cc5f8dd60e1680525f664d5b72be11fc6 Reviewed-on: https://go-review.googlesource.com/23220 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Andrew Gerrand <adg@golang.org>
1 parent 3b99394 commit 8aacbec

File tree

3 files changed

+63
-8
lines changed

3 files changed

+63
-8
lines changed

http2/go17.go

+22
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,33 @@ package http2
88

99
import (
1010
"context"
11+
"net"
1112
"net/http"
1213
"net/http/httptrace"
1314
"time"
1415
)
1516

17+
type contextContext interface {
18+
context.Context
19+
}
20+
21+
func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) {
22+
ctx, cancel = context.WithCancel(context.Background())
23+
ctx = context.WithValue(ctx, http.LocalAddrContextKey, c.LocalAddr())
24+
if hs := opts.baseConfig(); hs != nil {
25+
ctx = context.WithValue(ctx, http.ServerContextKey, hs)
26+
}
27+
return
28+
}
29+
30+
func contextWithCancel(ctx contextContext) (_ contextContext, cancel func()) {
31+
return context.WithCancel(ctx)
32+
}
33+
34+
func requestWithContext(req *http.Request, ctx contextContext) *http.Request {
35+
return req.WithContext(ctx)
36+
}
37+
1638
type clientTrace httptrace.ClientTrace
1739

1840
func reqContext(r *http.Request) context.Context { return r.Context() }

http2/not_go17.go

+20-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@
66

77
package http2
88

9-
import "net/http"
9+
import (
10+
"net"
11+
"net/http"
12+
)
13+
14+
type contextContext interface{}
1015

1116
type fakeContext struct{}
1217

@@ -28,3 +33,17 @@ func traceGotConn(*http.Request, *ClientConn) {}
2833
func traceFirstResponseByte(*clientTrace) {}
2934
func traceWroteHeaders(*clientTrace) {}
3035
func traceWroteRequest(*clientTrace, error) {}
36+
37+
func nop() {}
38+
39+
func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) {
40+
return nil, nop
41+
}
42+
43+
func contextWithCancel(ctx contextContext) (_ contextContext, cancel func()) {
44+
return ctx, nop
45+
}
46+
47+
func requestWithContext(req *http.Request, ctx contextContext) *http.Request {
48+
return req
49+
}

http2/server.go

+21-7
Original file line numberDiff line numberDiff line change
@@ -250,10 +250,14 @@ func (o *ServeConnOpts) handler() http.Handler {
250250
//
251251
// The opts parameter is optional. If nil, default values are used.
252252
func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
253+
baseCtx, cancel := serverConnBaseContext(c, opts)
254+
defer cancel()
255+
253256
sc := &serverConn{
254257
srv: s,
255258
hs: opts.baseConfig(),
256259
conn: c,
260+
baseCtx: baseCtx,
257261
remoteAddrStr: c.RemoteAddr().String(),
258262
bw: newBufferedWriter(c),
259263
handler: opts.handler(),
@@ -272,6 +276,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
272276
serveG: newGoroutineLock(),
273277
pushEnabled: true,
274278
}
279+
275280
sc.flow.add(initialWindowSize)
276281
sc.inflow.add(initialWindowSize)
277282
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
@@ -373,6 +378,7 @@ type serverConn struct {
373378
conn net.Conn
374379
bw *bufferedWriter // writing to conn
375380
handler http.Handler
381+
baseCtx contextContext
376382
framer *Framer
377383
doneServing chan struct{} // closed when serverConn.serve ends
378384
readFrameCh chan readFrameResult // written by serverConn.readFrames
@@ -436,10 +442,12 @@ func (sc *serverConn) maxHeaderListSize() uint32 {
436442
// responseWriter's state field.
437443
type stream struct {
438444
// immutable:
439-
sc *serverConn
440-
id uint32
441-
body *pipe // non-nil if expecting DATA frames
442-
cw closeWaiter // closed wait stream transitions to closed state
445+
sc *serverConn
446+
id uint32
447+
body *pipe // non-nil if expecting DATA frames
448+
cw closeWaiter // closed wait stream transitions to closed state
449+
ctx contextContext
450+
cancelCtx func()
443451

444452
// owned by serverConn's serve loop:
445453
bodyBytes int64 // body bytes seen so far
@@ -1157,6 +1165,7 @@ func (sc *serverConn) processResetStream(f *RSTStreamFrame) error {
11571165
}
11581166
if st != nil {
11591167
st.gotReset = true
1168+
st.cancelCtx()
11601169
sc.closeStream(st, StreamError{f.StreamID, f.ErrCode})
11611170
}
11621171
return nil
@@ -1380,10 +1389,13 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
13801389
}
13811390
sc.maxStreamID = id
13821391

1392+
ctx, cancelCtx := contextWithCancel(sc.baseCtx)
13831393
st = &stream{
1384-
sc: sc,
1385-
id: id,
1386-
state: stateOpen,
1394+
sc: sc,
1395+
id: id,
1396+
state: stateOpen,
1397+
ctx: ctx,
1398+
cancelCtx: cancelCtx,
13871399
}
13881400
if f.StreamEnded() {
13891401
st.state = stateHalfClosedRemote
@@ -1617,6 +1629,7 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
16171629
Body: body,
16181630
Trailer: trailer,
16191631
}
1632+
req = requestWithContext(req, st.ctx)
16201633
if bodyOpen {
16211634
// Disabled, per golang.org/issue/14960:
16221635
// st.reqBuf = sc.getRequestBodyBuf()
@@ -1661,6 +1674,7 @@ func (sc *serverConn) getRequestBodyBuf() []byte {
16611674
func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
16621675
didPanic := true
16631676
defer func() {
1677+
rw.rws.stream.cancelCtx()
16641678
if didPanic {
16651679
e := recover()
16661680
// Same as net/http:

0 commit comments

Comments
 (0)