rproxy: close the connection when a short answer is cut off (closes #318) #322
@@ -384,8 +384,19 @@ func (rq *request) refuse(status int) {
|
|||||||
func (rq *request) finish(ctx context.Context) {
|
func (rq *request) finish(ctx context.Context) {
|
||||||
rq.stopTimers()
|
rq.stopTimers()
|
||||||
|
|
||||||
if rq.refused.Load() == 0 {
|
// After a cut-off answer, the reading of a body that has not arrived whole
|
||||||
rq.stopPassingOnBody()
|
// ends now. Go's server would otherwise keep the connection open while it
|
||||||
|
// reads the rest. A flush fails if the time to send the answer ran out, and
|
||||||
|
// every flush after a failed one fails too. ReverseProxy ignores the failure,
|
||||||
|
// but panics if it was still waiting for more of the app's answer; finish runs
|
||||||
|
// either way. Before a status, a flush would send a 200; after a 101,
|
||||||
|
// ReverseProxy has taken over the connection.
|
||||||
|
switch {
|
||||||
|
case rq.out.status != 0 && rq.out.status != http.StatusSwitchingProtocols &&
|
||||||
|
errors.Is(rq.rc.Flush(), os.ErrDeadlineExceeded):
|
||||||
|
rq.stopPassingOnBody(time.Now())
|
||||||
|
case rq.refused.Load() == 0:
|
||||||
|
rq.stopPassingOnBody(rq.requestDeadline())
|
||||||
}
|
}
|
||||||
|
|
||||||
requestEnd := rq.endRequest()
|
requestEnd := rq.endRequest()
|
||||||
@@ -473,10 +484,10 @@ func (rq *request) stopReadingBody(deadline time.Time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// stopPassingOnBody ends the transport's reading of a visitor's body that has
|
// stopPassingOnBody ends the transport's reading of a visitor's body that has
|
||||||
// not arrived whole, and lets Go's server read the rest until
|
// not arrived whole, and lets Go's server read the rest until deadline. Go's
|
||||||
// SWRP_MAX_REQUEST_TIME_MS runs out. Go's server reads it once the handler
|
// server reads it once the handler returns, but with no deadline at all if
|
||||||
// returns, but with no deadline at all if another read of it is still waiting.
|
// another read of it is still waiting.
|
||||||
func (rq *request) stopPassingOnBody() {
|
func (rq *request) stopPassingOnBody(deadline time.Time) {
|
||||||
if rq.body == nil || rq.body.received.Load() {
|
if rq.body == nil || rq.body.received.Load() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -489,7 +500,7 @@ func (rq *request) stopPassingOnBody() {
|
|||||||
rq.body.stopped = true
|
rq.body.stopped = true
|
||||||
rq.body.mu.Unlock()
|
rq.body.mu.Unlock()
|
||||||
|
|
||||||
rq.stopReadingBody(rq.requestDeadline())
|
rq.stopReadingBody(deadline)
|
||||||
}
|
}
|
||||||
|
|
||||||
// startRequestTimer starts SWRP_MAX_REQUEST_TIME_MS, which runs from the
|
// startRequestTimer starts SWRP_MAX_REQUEST_TIME_MS, which runs from the
|
||||||
|
|||||||
Reference in new issue
Block a user