Skip to content

Commit 4759a80

Browse files
jindijamiek8s-publishing-bot
authored andcommitted
Add an option for aggregator
Kubernetes-commit: 474db7298469d7f75dff42a30a28749eaaa81874
1 parent 10b456c commit 4759a80

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

pkg/util/proxy/upgradeaware.go

+27
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ type UpgradeAwareHandler struct {
8383
MaxBytesPerSec int64
8484
// Responder is passed errors that occur while setting up proxying.
8585
Responder ErrorResponder
86+
// Reject to forward redirect response
87+
RejectForwardingRedirects bool
8688
}
8789

8890
const defaultFlushInterval = 200 * time.Millisecond
@@ -257,6 +259,31 @@ func (h *UpgradeAwareHandler) ServeHTTP(w http.ResponseWriter, req *http.Request
257259
proxy.Transport = h.Transport
258260
proxy.FlushInterval = h.FlushInterval
259261
proxy.ErrorLog = log.New(noSuppressPanicError{}, "", log.LstdFlags)
262+
if h.RejectForwardingRedirects {
263+
oldModifyResponse := proxy.ModifyResponse
264+
proxy.ModifyResponse = func(response *http.Response) error {
265+
code := response.StatusCode
266+
if code >= 300 && code <= 399 {
267+
// close the original response
268+
response.Body.Close()
269+
msg := "the backend attempted to redirect this request, which is not permitted"
270+
// replace the response
271+
*response = http.Response{
272+
StatusCode: http.StatusBadGateway,
273+
Status: fmt.Sprintf("%d %s", response.StatusCode, http.StatusText(response.StatusCode)),
274+
Body: io.NopCloser(strings.NewReader(msg)),
275+
ContentLength: int64(len(msg)),
276+
}
277+
} else {
278+
if oldModifyResponse != nil {
279+
if err := oldModifyResponse(response); err != nil {
280+
return err
281+
}
282+
}
283+
}
284+
return nil
285+
}
286+
}
260287
if h.Responder != nil {
261288
// if an optional error interceptor/responder was provided wire it
262289
// the custom responder might be used for providing a unified error reporting

pkg/util/proxy/upgradeaware_test.go

+77
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,83 @@ func TestProxyUpgradeErrorResponse(t *testing.T) {
704704
}
705705
}
706706

707+
func TestRejectForwardingRedirectsOption(t *testing.T) {
708+
originalBody := []byte(`some data`)
709+
testCases := []struct {
710+
name string
711+
rejectForwardingRedirects bool
712+
serverStatusCode int
713+
expectStatusCode int
714+
expectBody []byte
715+
}{
716+
{
717+
name: "reject redirection enabled in proxy, backend server sending 200 response",
718+
rejectForwardingRedirects: true,
719+
serverStatusCode: 200,
720+
expectStatusCode: 200,
721+
expectBody: originalBody,
722+
},
723+
{
724+
name: "reject redirection enabled in proxy, backend server sending 301 response",
725+
rejectForwardingRedirects: true,
726+
serverStatusCode: 301,
727+
expectStatusCode: 502,
728+
expectBody: []byte(`the backend attempted to redirect this request, which is not permitted`),
729+
},
730+
{
731+
name: "reject redirection disabled in proxy, backend server sending 200 response",
732+
rejectForwardingRedirects: false,
733+
serverStatusCode: 200,
734+
expectStatusCode: 200,
735+
expectBody: originalBody,
736+
},
737+
{
738+
name: "reject redirection disabled in proxy, backend server sending 301 response",
739+
rejectForwardingRedirects: false,
740+
serverStatusCode: 301,
741+
expectStatusCode: 301,
742+
expectBody: originalBody,
743+
},
744+
}
745+
for _, tc := range testCases {
746+
t.Run(tc.name, func(t *testing.T) {
747+
// Set up a backend server
748+
backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
749+
w.WriteHeader(tc.serverStatusCode)
750+
w.Write(originalBody)
751+
}))
752+
defer backendServer.Close()
753+
backendServerURL, _ := url.Parse(backendServer.URL)
754+
755+
// Set up a proxy pointing to the backend
756+
proxyHandler := NewUpgradeAwareHandler(backendServerURL, nil, false, false, &fakeResponder{t: t})
757+
proxyHandler.RejectForwardingRedirects = tc.rejectForwardingRedirects
758+
proxy := httptest.NewServer(proxyHandler)
759+
defer proxy.Close()
760+
proxyURL, _ := url.Parse(proxy.URL)
761+
762+
conn, err := net.Dial("tcp", proxyURL.Host)
763+
require.NoError(t, err)
764+
bufferedReader := bufio.NewReader(conn)
765+
766+
req, _ := http.NewRequest("GET", proxyURL.String(), nil)
767+
require.NoError(t, req.Write(conn))
768+
// Verify we get the correct response and message body content
769+
resp, err := http.ReadResponse(bufferedReader, nil)
770+
require.NoError(t, err)
771+
assert.Equal(t, tc.expectStatusCode, resp.StatusCode)
772+
data, err := ioutil.ReadAll(resp.Body)
773+
require.NoError(t, err)
774+
assert.Equal(t, tc.expectBody, data)
775+
assert.Equal(t, int64(len(tc.expectBody)), resp.ContentLength)
776+
resp.Body.Close()
777+
778+
// clean up
779+
conn.Close()
780+
})
781+
}
782+
}
783+
707784
func TestDefaultProxyTransport(t *testing.T) {
708785
tests := []struct {
709786
name,

0 commit comments

Comments
 (0)