rproxy: answer a visitor that stops sending its body after the app has answered (closes #298)
check / check (push) Failing after 5m10s
check / check (push) Failing after 5m10s
When the app answered before the visitor's body had arrived whole, Go's server read up to 256 KiB of the rest before it sent the answer. A visitor that stopped sending got nothing until SWRP_MAX_REQUEST_TIME_MS ran out, and no bytes at all once that was past the 10 seconds the status has to be sent. Such an answer now carries Connection: close, which Go sends at once. finish first ends the transport's read of the body: once the handler returns, Go's server reads the rest with no deadline while another read of it waits. requestBody.Close does nothing, so that ReverseProxy's close does not wait on the visitor. Model: opus-5-5
This commit is contained in:
1 parent
abb8a26a48
commit
fff8212604
4 files changed
+156
-20
No files matched your search
@@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
@@ -31,11 +32,24 @@ type requestBody struct {
|
||||
received atomic.Bool
|
||||
// bytes is how much of the body has been read.
|
||||
bytes atomic.Int64
|
||||
|
||||
// mu is held for the whole of each Read, and guards stopped.
|
||||
mu sync.Mutex
|
||||
// stopped is true once the body no longer goes to the app; Read then reads
|
||||
// no more.
|
||||
stopped bool
|
||||
}
|
||||
|
||||
// Read reads from the visitor's body, after the part held, which has been
|
||||
// counted already.
|
||||
func (b *requestBody) Read(p []byte) (int, error) {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
|
||||
if b.stopped {
|
||||
return 0, http.ErrBodyReadAfterClose
|
||||
}
|
||||
|
||||
if len(b.held) > 0 {
|
||||
n := copy(p, b.held)
|
||||
b.held = b.held[n:]
|
||||
@@ -60,9 +74,11 @@ func (b *requestBody) Read(p []byte) (int, error) {
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Close closes the visitor's body.
|
||||
// Close does nothing: Go's server closes the visitor's body once the handler
|
||||
// returns. Closing it earlier, as the transport and ReverseProxy do, would wait
|
||||
// for a Read in progress and then read up to 256 KiB more of the body.
|
||||
func (b *requestBody) Close() error {
|
||||
return b.body.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
// responseBody is the app's response body on its way to the visitor.
|
||||
|
||||
Reference in new issue
Block a user