aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Liggitt <liggitt@google.com>2019-03-28 23:37:54 -0400
committerBrad Fitzpatrick <bradfitz@golang.org>2019-04-02 03:09:03 +0000
commitec06e9ba4578d26fdb9c521d4042e3f9f7f42435 (patch)
treec67e293ea0fee6ff64e937297372c4877b49f05f
parentaeb9d03e4a570890b32aafd7aee27b00946ebbe4 (diff)
downloadgo-ec06e9ba4578d26fdb9c521d4042e3f9f7f42435.tar.gz
go-ec06e9ba4578d26fdb9c521d4042e3f9f7f42435.zip
[release-branch.go1.12] net/http/httputil: make ReverseProxy flush headers on FlushInterval
A regression was introduced in CL 137335 (5440bfc) that caused FlushInterval to not be honored until the first Write() call was encountered. This change starts the flush timer as part of setting up the maxLatencyWriter. Fixes #31144 Change-Id: I75325bd926652922219bd1457b2b00ac6d0d41b0 Reviewed-on: https://go-review.googlesource.com/c/go/+/170066 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> (cherry picked from commit 2cc347382f4df3fb40d8d81ec9331f0748b1c394) Reviewed-on: https://go-review.googlesource.com/c/go/+/170137
-rw-r--r--src/net/http/httputil/reverseproxy.go5
-rw-r--r--src/net/http/httputil/reverseproxy_test.go42
2 files changed, 47 insertions, 0 deletions
diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
index 4e10bf3997..4b165d65a6 100644
--- a/src/net/http/httputil/reverseproxy.go
+++ b/src/net/http/httputil/reverseproxy.go
@@ -389,6 +389,11 @@ func (p *ReverseProxy) copyResponse(dst io.Writer, src io.Reader, flushInterval
latency: flushInterval,
}
defer mlw.stop()
+
+ // set up initial timer so headers get flushed even if body writes are delayed
+ mlw.flushPending = true
+ mlw.t = time.AfterFunc(flushInterval, mlw.delayedFlush)
+
dst = mlw
}
}
diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go
index 5edefa08e5..367ba73ae2 100644
--- a/src/net/http/httputil/reverseproxy_test.go
+++ b/src/net/http/httputil/reverseproxy_test.go
@@ -9,6 +9,7 @@ package httputil
import (
"bufio"
"bytes"
+ "context"
"errors"
"fmt"
"io"
@@ -317,6 +318,47 @@ func TestReverseProxyFlushInterval(t *testing.T) {
}
}
+func TestReverseProxyFlushIntervalHeaders(t *testing.T) {
+ const expected = "hi"
+ stopCh := make(chan struct{})
+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Add("MyHeader", expected)
+ w.WriteHeader(200)
+ w.(http.Flusher).Flush()
+ <-stopCh
+ }))
+ defer backend.Close()
+ defer close(stopCh)
+
+ backendURL, err := url.Parse(backend.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ proxyHandler := NewSingleHostReverseProxy(backendURL)
+ proxyHandler.FlushInterval = time.Microsecond
+
+ frontend := httptest.NewServer(proxyHandler)
+ defer frontend.Close()
+
+ req, _ := http.NewRequest("GET", frontend.URL, nil)
+ req.Close = true
+
+ ctx, cancel := context.WithTimeout(req.Context(), 10*time.Second)
+ defer cancel()
+ req = req.WithContext(ctx)
+
+ res, err := frontend.Client().Do(req)
+ if err != nil {
+ t.Fatalf("Get: %v", err)
+ }
+ defer res.Body.Close()
+
+ if res.Header.Get("MyHeader") != expected {
+ t.Errorf("got header %q; expected %q", res.Header.Get("MyHeader"), expected)
+ }
+}
+
func TestReverseProxyCancelation(t *testing.T) {
const backendResponse = "I am the backend"