Merge branch 'v2.1' into master
This commit is contained in:
commit
da3d814c8b
56 changed files with 2162 additions and 558 deletions
|
@ -10,7 +10,7 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
_ middlewares.Stateful = &captureResponseWriter{}
|
||||
_ middlewares.Stateful = &captureResponseWriterWithCloseNotify{}
|
||||
)
|
||||
|
||||
type capturer interface {
|
||||
|
@ -24,7 +24,7 @@ func newCaptureResponseWriter(rw http.ResponseWriter) capturer {
|
|||
if _, ok := rw.(http.CloseNotifier); !ok {
|
||||
return capt
|
||||
}
|
||||
return captureResponseWriterWithCloseNotify{capt}
|
||||
return &captureResponseWriterWithCloseNotify{capt}
|
||||
}
|
||||
|
||||
// captureResponseWriter is a wrapper of type http.ResponseWriter
|
||||
|
@ -76,13 +76,6 @@ func (crw *captureResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error)
|
|||
return nil, nil, fmt.Errorf("not a hijacker: %T", crw.rw)
|
||||
}
|
||||
|
||||
func (crw *captureResponseWriter) CloseNotify() <-chan bool {
|
||||
if c, ok := crw.rw.(http.CloseNotifier); ok {
|
||||
return c.CloseNotify()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (crw *captureResponseWriter) Status() int {
|
||||
return crw.status
|
||||
}
|
||||
|
|
50
pkg/middlewares/accesslog/capture_response_writer_test.go
Normal file
50
pkg/middlewares/accesslog/capture_response_writer_test.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
package accesslog
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type rwWithCloseNotify struct {
|
||||
*httptest.ResponseRecorder
|
||||
}
|
||||
|
||||
func (r *rwWithCloseNotify) CloseNotify() <-chan bool {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func TestCloseNotifier(t *testing.T) {
|
||||
testCases := []struct {
|
||||
rw http.ResponseWriter
|
||||
desc string
|
||||
implementsCloseNotifier bool
|
||||
}{
|
||||
{
|
||||
rw: httptest.NewRecorder(),
|
||||
desc: "does not implement CloseNotifier",
|
||||
implementsCloseNotifier: false,
|
||||
},
|
||||
{
|
||||
rw: &rwWithCloseNotify{httptest.NewRecorder()},
|
||||
desc: "implements CloseNotifier",
|
||||
implementsCloseNotifier: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, ok := test.rw.(http.CloseNotifier)
|
||||
assert.Equal(t, test.implementsCloseNotifier, ok)
|
||||
|
||||
rw := newCaptureResponseWriter(test.rw)
|
||||
_, impl := rw.(http.CloseNotifier)
|
||||
assert.Equal(t, test.implementsCloseNotifier, impl)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -88,9 +88,11 @@ func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
writeHeader(req, forwardReq, fa.trustForwardHeader)
|
||||
// Ensure tracing headers are in the request before we copy the headers to the
|
||||
// forwardReq.
|
||||
tracing.InjectRequestHeaders(req)
|
||||
|
||||
tracing.InjectRequestHeaders(forwardReq)
|
||||
writeHeader(req, forwardReq, fa.trustForwardHeader)
|
||||
|
||||
forwardResponse, forwardErr := httpClient.Do(forwardReq)
|
||||
if forwardErr != nil {
|
||||
|
|
|
@ -3,13 +3,18 @@ package auth
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||
tracingMiddleware "github.com/containous/traefik/v2/pkg/middlewares/tracing"
|
||||
"github.com/containous/traefik/v2/pkg/testhelpers"
|
||||
"github.com/containous/traefik/v2/pkg/tracing"
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"github.com/opentracing/opentracing-go/mocktracer"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/vulcand/oxy/forward"
|
||||
|
@ -394,3 +399,44 @@ func Test_writeHeader(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestForwardAuthUsesTracing(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("Mockpfx-Ids-Traceid") == "" {
|
||||
t.Errorf("expected Mockpfx-Ids-Traceid header to be present in request")
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
next := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
|
||||
|
||||
auth := dynamic.ForwardAuth{
|
||||
Address: server.URL,
|
||||
}
|
||||
|
||||
tracer := mocktracer.New()
|
||||
opentracing.SetGlobalTracer(tracer)
|
||||
|
||||
tr, _ := tracing.NewTracing("testApp", 100, &mockBackend{tracer})
|
||||
|
||||
next, err := NewForward(context.Background(), next, auth, "authTest")
|
||||
require.NoError(t, err)
|
||||
|
||||
next = tracingMiddleware.NewEntryPoint(context.Background(), tr, "tracingTest", next)
|
||||
|
||||
ts := httptest.NewServer(next)
|
||||
defer ts.Close()
|
||||
|
||||
req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil)
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode)
|
||||
}
|
||||
|
||||
type mockBackend struct {
|
||||
opentracing.Tracer
|
||||
}
|
||||
|
||||
func (b *mockBackend) Setup(componentName string) (opentracing.Tracer, io.Closer, error) {
|
||||
return b.Tracer, ioutil.NopCloser(nil), nil
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/go-kit/kit/metrics"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// CollectingCounter is a metrics.Counter implementation that enables access to the CounterValue and LastLabelValues.
|
||||
|
@ -56,3 +57,44 @@ func newCollectingRetryMetrics() *collectingRetryMetrics {
|
|||
func (m *collectingRetryMetrics) ServiceRetriesCounter() metrics.Counter {
|
||||
return m.retriesCounter
|
||||
}
|
||||
|
||||
type rwWithCloseNotify struct {
|
||||
*httptest.ResponseRecorder
|
||||
}
|
||||
|
||||
func (r *rwWithCloseNotify) CloseNotify() <-chan bool {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func TestCloseNotifier(t *testing.T) {
|
||||
testCases := []struct {
|
||||
rw http.ResponseWriter
|
||||
desc string
|
||||
implementsCloseNotifier bool
|
||||
}{
|
||||
{
|
||||
rw: httptest.NewRecorder(),
|
||||
desc: "does not implement CloseNotifier",
|
||||
implementsCloseNotifier: false,
|
||||
},
|
||||
{
|
||||
rw: &rwWithCloseNotify{httptest.NewRecorder()},
|
||||
desc: "implements CloseNotifier",
|
||||
implementsCloseNotifier: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, ok := test.rw.(http.CloseNotifier)
|
||||
assert.Equal(t, test.implementsCloseNotifier, ok)
|
||||
|
||||
rw := newResponseRecorder(test.rw)
|
||||
_, impl := rw.(http.CloseNotifier)
|
||||
assert.Equal(t, test.implementsCloseNotifier, impl)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ func newResponseRecorder(rw http.ResponseWriter) recorder {
|
|||
if _, ok := rw.(http.CloseNotifier); !ok {
|
||||
return rec
|
||||
}
|
||||
return responseRecorderWithCloseNotify{rec}
|
||||
return &responseRecorderWithCloseNotify{rec}
|
||||
}
|
||||
|
||||
// responseRecorder captures information from the response and preserves it for
|
||||
|
@ -55,13 +55,6 @@ func (r *responseRecorder) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
|||
return r.ResponseWriter.(http.Hijacker).Hijack()
|
||||
}
|
||||
|
||||
// CloseNotify returns a channel that receives at most a
|
||||
// single value (true) when the client connection has gone
|
||||
// away.
|
||||
func (r *responseRecorder) CloseNotify() <-chan bool {
|
||||
return r.ResponseWriter.(http.CloseNotifier).CloseNotify()
|
||||
}
|
||||
|
||||
// Flush sends any buffered data to the client.
|
||||
func (r *responseRecorder) Flush() {
|
||||
if f, ok := r.ResponseWriter.(http.Flusher); ok {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue