@@ -9,6 +9,7 @@ package http
9
9
import (
10
10
"bufio"
11
11
"bytes"
12
+ "context"
12
13
"crypto/tls"
13
14
"errors"
14
15
"fmt"
@@ -312,10 +313,11 @@ type response struct {
312
313
conn * conn
313
314
req * Request // request for this response
314
315
reqBody io.ReadCloser
315
- wroteHeader bool // reply header has been (logically) written
316
- wroteContinue bool // 100 Continue response was written
317
- wants10KeepAlive bool // HTTP/1.0 w/ Connection "keep-alive"
318
- wantsClose bool // HTTP request has Connection "close"
316
+ cancelCtx context.CancelFunc // when ServeHTTP exits
317
+ wroteHeader bool // reply header has been (logically) written
318
+ wroteContinue bool // 100 Continue response was written
319
+ wants10KeepAlive bool // HTTP/1.0 w/ Connection "keep-alive"
320
+ wantsClose bool // HTTP request has Connection "close"
319
321
320
322
w * bufio.Writer // buffers output in chunks to chunkWriter
321
323
cw chunkWriter
@@ -686,7 +688,7 @@ func appendTime(b []byte, t time.Time) []byte {
686
688
var errTooLarge = errors .New ("http: request too large" )
687
689
688
690
// Read next request from connection.
689
- func (c * conn ) readRequest () (w * response , err error ) {
691
+ func (c * conn ) readRequest (ctx context. Context ) (w * response , err error ) {
690
692
if c .hijacked () {
691
693
return nil , ErrHijacked
692
694
}
@@ -715,6 +717,10 @@ func (c *conn) readRequest() (w *response, err error) {
715
717
}
716
718
return nil , err
717
719
}
720
+
721
+ ctx , cancelCtx := context .WithCancel (ctx )
722
+ req .ctx = ctx
723
+
718
724
c .lastMethod = req .Method
719
725
c .r .setInfiniteReadLimit ()
720
726
@@ -749,6 +755,7 @@ func (c *conn) readRequest() (w *response, err error) {
749
755
750
756
w = & response {
751
757
conn : c ,
758
+ cancelCtx : cancelCtx ,
752
759
req : req ,
753
760
reqBody : req .Body ,
754
761
handlerHeader : make (Header ),
@@ -1432,12 +1439,20 @@ func (c *conn) serve() {
1432
1439
}
1433
1440
}
1434
1441
1442
+ // HTTP/1.x from here on.
1443
+
1435
1444
c .r = & connReader {r : c .rwc }
1436
1445
c .bufr = newBufioReader (c .r )
1437
1446
c .bufw = newBufioWriterSize (checkConnErrorWriter {c }, 4 << 10 )
1438
1447
1448
+ // TODO: allow changing base context? can't imagine concrete
1449
+ // use cases yet.
1450
+ baseCtx := context .Background ()
1451
+ ctx , cancelCtx := context .WithCancel (baseCtx )
1452
+ defer cancelCtx ()
1453
+
1439
1454
for {
1440
- w , err := c .readRequest ()
1455
+ w , err := c .readRequest (ctx )
1441
1456
if c .r .remain != c .server .initialReadLimitSize () {
1442
1457
// If we read any bytes off the wire, we're active.
1443
1458
c .setState (c .rwc , StateActive )
@@ -1485,6 +1500,7 @@ func (c *conn) serve() {
1485
1500
// [*] Not strictly true: HTTP pipelining. We could let them all process
1486
1501
// in parallel even if their responses need to be serialized.
1487
1502
serverHandler {c .server }.ServeHTTP (w , w .req )
1503
+ w .cancelCtx ()
1488
1504
if c .hijacked () {
1489
1505
return
1490
1506
}
0 commit comments