Skip to content

Commit

Permalink
Merge pull request #52933 from liggitt/proxy-subpath-slash
Browse files Browse the repository at this point in the history
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>..

Preserve leading and trailing slashes on proxy subpaths

subresource parsing was not populating path parameters correctly (leading and trailing slashes were being stripped)

this caused bad locations to be sent to the proxy, causing kubernetes/kubernetes#52022. the first attempt to fix that (#52065) unconditionally prefixed '/', which broke the redirect case (#52813 #52729)

fixes #52813, fixes #52729

needs to be picked to 1.7 and 1.8

```release-note
Restores redirect behavior for proxy subresources
```

Kubernetes-commit: e0f75338b5720fbce0aa02b0cf79965950089dbc
  • Loading branch information
k8s-publishing-bot committed Sep 23, 2017
2 parents be971f2 + 06d00b1 commit ef64f22
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 0 deletions.
21 changes: 21 additions & 0 deletions pkg/util/net/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,34 @@ import (
"net/http"
"net/url"
"os"
"path"
"strconv"
"strings"

"github.com/golang/glog"
"golang.org/x/net/http2"
)

// JoinPreservingTrailingSlash does a path.Join of the specified elements,
// preserving any trailing slash on the last non-empty segment
func JoinPreservingTrailingSlash(elem ...string) string {
// do the basic path join
result := path.Join(elem...)

// find the last non-empty segment
for i := len(elem) - 1; i >= 0; i-- {
if len(elem[i]) > 0 {
// if the last segment ended in a slash, ensure our result does as well
if strings.HasSuffix(elem[i], "/") && !strings.HasSuffix(result, "/") {
result += "/"
}
break
}
}

return result
}

// IsProbableEOF returns true if the given error resembles a connection termination
// scenario that would justify assuming that the watch is empty.
// These errors are what the Go http stack returns back to us which are general
Expand Down
38 changes: 38 additions & 0 deletions pkg/util/net/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package net

import (
"crypto/tls"
"fmt"
"net"
"net/http"
"net/url"
Expand Down Expand Up @@ -218,3 +219,40 @@ func TestTLSClientConfigHolder(t *testing.T) {
t.Errorf("didn't find tls config")
}
}

func TestJoinPreservingTrailingSlash(t *testing.T) {
tests := []struct {
a string
b string
want string
}{
// All empty
{"", "", ""},

// Empty a
{"", "/", "/"},
{"", "foo", "foo"},
{"", "/foo", "/foo"},
{"", "/foo/", "/foo/"},

// Empty b
{"/", "", "/"},
{"foo", "", "foo"},
{"/foo", "", "/foo"},
{"/foo/", "", "/foo/"},

// Both populated
{"/", "/", "/"},
{"foo", "foo", "foo/foo"},
{"/foo", "/foo", "/foo/foo"},
{"/foo/", "/foo/", "/foo/foo/"},
}
for _, tt := range tests {
name := fmt.Sprintf("%q+%q=%q", tt.a, tt.b, tt.want)
t.Run(name, func(t *testing.T) {
if got := JoinPreservingTrailingSlash(tt.a, tt.b); got != tt.want {
t.Errorf("JoinPreservingTrailingSlash() = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit ef64f22

Please sign in to comment.