rproxy: give its own answers at least 10 seconds to be sent (closes #295)
check / check (push) Successful in 3m52s
check / check (push) Successful in 3m52s
The write deadline of an answer rproxy gives itself was SWRP_MAX_RESPONSE_TIME_MS from when the answer started. With a limit under a second, a host too busy to run rproxy for that long passes the deadline before the first byte is written. Go then closes the connection and the visitor gets no answer. Model: opus-5-5
This commit is contained in:
1 parent
8ab4280792
commit
27835a703f
4 files changed
+35
-4
No files matched your search
@@ -481,6 +481,30 @@ func TestAnAnswerRProxyGivesItselfHasTheResponseTimeToBeSent(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnAnswerRProxyGivesItselfHasTenSecondsToBeSentAtLeast(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const least = 10 * time.Second
|
||||
|
||||
standIn := startDiscriminator(t, deny)
|
||||
app := startApp(t, greet)
|
||||
_, _, server := startServer(t, standIn.URL, app.URL, map[string]string{
|
||||
maxResponseTime: "300",
|
||||
})
|
||||
|
||||
req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/", http.NoBody)
|
||||
w := &deadlineRecorder{ResponseRecorder: httptest.NewRecorder()}
|
||||
|
||||
before := time.Now()
|
||||
|
||||
server.Handler.ServeHTTP(w, req)
|
||||
|
||||
if w.writeDeadline.Before(before.Add(least)) {
|
||||
t.Errorf("the time limit on sending ends at %s, want %s from the answer at least",
|
||||
w.writeDeadline, least)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAVisitorTooSlowToSendTheRestIsAnswered408(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
@@ -32,6 +32,11 @@ const reportStatusMax = 599
|
||||
// plainText is the Content-Type of the answers rproxy gives itself.
|
||||
const plainText = "text/plain; charset=utf-8"
|
||||
|
||||
// ownAnswerMinSendTime is the least time an answer rproxy gives itself has to be
|
||||
// sent. A shorter time can run out on a busy host before the first byte is
|
||||
// written, and the visitor then gets a closed connection and no answer.
|
||||
const ownAnswerMinSendTime = 10 * time.Second
|
||||
|
||||
// request is one request on its way through rproxy, from the moment its headers
|
||||
// have been read to its log line and report.
|
||||
type request struct {
|
||||
@@ -326,14 +331,14 @@ func (rq *request) send(status int, body []byte) {
|
||||
// prepareOwnAnswer readies the connection for an answer rproxy gives itself: the
|
||||
// reading of a body that has not arrived whole ends at deadline, and the answer
|
||||
// has SWRP_MAX_RESPONSE_TIME_MS from now to reach the visitor, even when the app
|
||||
// used that time up first.
|
||||
// used that time up first, and at least ownAnswerMinSendTime.
|
||||
func (rq *request) prepareOwnAnswer(deadline time.Time) {
|
||||
rq.stopReadingBody(deadline)
|
||||
rq.endRequest()
|
||||
|
||||
limit := rq.h.config.MaxResponseTime
|
||||
if limit > 0 {
|
||||
_ = rq.rc.SetWriteDeadline(time.Now().Add(limit))
|
||||
_ = rq.rc.SetWriteDeadline(time.Now().Add(max(limit, ownAnswerMinSendTime)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user