Commit 38c76647 authored by Tw's avatar Tw Committed by Matt Holt

proxy: use a new context for the outgoing request (#1358)

* proxy: use a new context for the outgoing request

fix issue #1345
Signed-off-by: default avatarTw <tw19881113@gmail.com>

* proxy: add test for canceling the request
Signed-off-by: default avatarTw <tw19881113@gmail.com>
parent 696b46f0
...@@ -3,6 +3,7 @@ package proxy ...@@ -3,6 +3,7 @@ package proxy
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"context"
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"io" "io"
...@@ -11,6 +12,7 @@ import ( ...@@ -11,6 +12,7 @@ import (
"net" "net"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"net/http/httptrace"
"net/url" "net/url"
"os" "os"
"path/filepath" "path/filepath"
...@@ -1017,6 +1019,47 @@ func TestReverseProxyLargeBody(t *testing.T) { ...@@ -1017,6 +1019,47 @@ func TestReverseProxyLargeBody(t *testing.T) {
} }
} }
func TestCancelRequest(t *testing.T) {
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, client"))
}))
defer backend.Close()
// set up proxy
p := &Proxy{
Next: httpserver.EmptyNext, // prevents panic in some cases when test fails
Upstreams: []Upstream{newFakeUpstream(backend.URL, false)},
}
// setup request with cancel ctx
req := httptest.NewRequest("GET", "/", nil)
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
req = req.WithContext(ctx)
// add GotConn hook to cancel the request
gotC := make(chan struct{})
defer close(gotC)
trace := &httptrace.ClientTrace{
GotConn: func(connInfo httptrace.GotConnInfo) {
gotC <- struct{}{}
},
}
req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
// wait for canceling the request
go func() {
<-gotC
cancel()
}()
status, err := p.ServeHTTP(httptest.NewRecorder(), req)
if status != 0 || err != nil {
t.Errorf("expect proxy handle normally, but not, status:%d, err:%q",
status, err)
}
}
type noopReader struct { type noopReader struct {
len uint64 len uint64
pos uint64 pos uint64
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
package proxy package proxy
import ( import (
"context"
"crypto/tls" "crypto/tls"
"io" "io"
"net" "net"
...@@ -206,6 +207,14 @@ func (rp *ReverseProxy) ServeHTTP(rw http.ResponseWriter, outreq *http.Request, ...@@ -206,6 +207,14 @@ func (rp *ReverseProxy) ServeHTTP(rw http.ResponseWriter, outreq *http.Request,
rp.Director(outreq) rp.Director(outreq)
// Original incoming server request may be canceled by the
// user or by std lib(e.g. too many idle connections).
// Now we issue the new outgoing client request which
// doesn't depend on the original one. (issue 1345)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
outreq = outreq.WithContext(ctx)
res, err := transport.RoundTrip(outreq) res, err := transport.RoundTrip(outreq)
if err != nil { if err != nil {
return err return err
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment