mirror of
https://github.com/golang/go
synced 2024-11-18 06:04:53 -07:00
net/http/httputil: log err encountered during reverseproxy body copying
Fixes #16659 Change-Id: I13dd797e93e0b572eaf8726f1be594870d40183b Reviewed-on: https://go-review.googlesource.com/30692 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
95f3e47456
commit
a7cad4110a
@ -260,12 +260,40 @@ func (p *ReverseProxy) copyResponse(dst io.Writer, src io.Reader) {
|
||||
if p.BufferPool != nil {
|
||||
buf = p.BufferPool.Get()
|
||||
}
|
||||
io.CopyBuffer(dst, src, buf)
|
||||
p.copyBuffer(dst, src, buf)
|
||||
if p.BufferPool != nil {
|
||||
p.BufferPool.Put(buf)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ReverseProxy) copyBuffer(dst io.Writer, src io.Reader, buf []byte) (int64, error) {
|
||||
if len(buf) == 0 {
|
||||
buf = make([]byte, 32*1024)
|
||||
}
|
||||
var written int64
|
||||
for {
|
||||
nr, rerr := src.Read(buf)
|
||||
if rerr != nil && rerr != io.EOF {
|
||||
p.logf("httputil: ReverseProxy read error during body copy: %v", rerr)
|
||||
}
|
||||
if nr > 0 {
|
||||
nw, werr := dst.Write(buf[:nr])
|
||||
if nw > 0 {
|
||||
written += int64(nw)
|
||||
}
|
||||
if werr != nil {
|
||||
return written, werr
|
||||
}
|
||||
if nr != nw {
|
||||
return written, io.ErrShortWrite
|
||||
}
|
||||
}
|
||||
if rerr != nil {
|
||||
return written, rerr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ReverseProxy) logf(format string, args ...interface{}) {
|
||||
if p.ErrorLog != nil {
|
||||
p.ErrorLog.Printf(format, args...)
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
@ -581,3 +582,44 @@ func TestReverseProxy_NilBody(t *testing.T) {
|
||||
t.Errorf("status code = %v; want 502 (Gateway Error)", res.Status)
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 16659: log errors from short read
|
||||
func TestReverseProxy_CopyBuffer(t *testing.T) {
|
||||
backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
out := "this call was relayed by the reverse proxy"
|
||||
// Coerce a wrong content length to induce io.UnexpectedEOF
|
||||
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(out)*2))
|
||||
fmt.Fprintln(w, out)
|
||||
}))
|
||||
defer backendServer.Close()
|
||||
|
||||
rpURL, err := url.Parse(backendServer.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var proxyLog bytes.Buffer
|
||||
rproxy := NewSingleHostReverseProxy(rpURL)
|
||||
rproxy.ErrorLog = log.New(&proxyLog, "", log.Lshortfile)
|
||||
frontendProxy := httptest.NewServer(rproxy)
|
||||
defer frontendProxy.Close()
|
||||
|
||||
resp, err := http.Get(frontendProxy.URL)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to reach proxy: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if _, err := ioutil.ReadAll(resp.Body); err == nil {
|
||||
t.Fatalf("want non-nil error")
|
||||
}
|
||||
expected := []string{
|
||||
"EOF",
|
||||
"read",
|
||||
}
|
||||
for _, phrase := range expected {
|
||||
if !bytes.Contains(proxyLog.Bytes(), []byte(phrase)) {
|
||||
t.Errorf("expected log to contain phrase %q", phrase)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user