Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow redirect URI path to not be normalized. #1638

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1064,16 +1064,17 @@ func doRequestFollowRedirects(req *Request, resp *Response, url string, maxRedir
err = ErrMissingLocation
break
}
url = getRedirectURL(url, location)
url = getRedirectURL(url, location, req.DisableRedirectPathNormalizing)
}

return statusCode, body, err
}

func getRedirectURL(baseURL string, location []byte) string {
func getRedirectURL(baseURL string, location []byte, disablePathNormalizing bool) string {
u := AcquireURI()
u.Update(baseURL)
u.UpdateBytes(location)
u.DisablePathNormalizing = disablePathNormalizing
redirectURL := u.String()
ReleaseURI(u)
return redirectURL
Expand Down
86 changes: 86 additions & 0 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1589,6 +1589,10 @@ func TestClientFollowRedirects(t *testing.T) {
u := ctx.URI()
u.Update("/bar")
ctx.Redirect(u.String(), StatusFound)
case "/abc/*/123":
u := ctx.URI()
u.Update("/xyz/*/456")
ctx.Redirect(u.String(), StatusFound)
default:
ctx.Success("text/plain", ctx.Path())
}
Expand Down Expand Up @@ -1710,6 +1714,31 @@ func TestClientFollowRedirects(t *testing.T) {
ReleaseResponse(resp)
}

for i := 0; i < 10; i++ {
req := AcquireRequest()
resp := AcquireResponse()

req.SetRequestURI("http://xxx/abc/*/123")
req.URI().DisablePathNormalizing = true
req.DisableRedirectPathNormalizing = true

err := c.DoRedirects(req, resp, 16)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

if statusCode := resp.StatusCode(); statusCode != StatusOK {
t.Fatalf("unexpected status code: %d", statusCode)
}

if body := string(resp.Body()); body != "/xyz/*/456" {
t.Fatalf("unexpected response %q. Expecting %q", body, "/xyz/*/456")
}

ReleaseRequest(req)
ReleaseResponse(resp)
}

req := AcquireRequest()
resp := AcquireResponse()

Expand Down Expand Up @@ -3306,3 +3335,60 @@ func TestClientTransportEx(t *testing.T) {
t.Errorf("round trip count should be: %v", roundTripCount)
}
}

func Test_getRedirectURL(t *testing.T) {
type args struct {
baseURL string
location []byte
disablePathNormalizing bool
}
tests := []struct {
name string
args args
want string
}{
{
name: "Path normalizing enabled, no special characters in path",
args: args{
baseURL: "http://foo.example.com/abc",
location: []byte("http://bar.example.com/def"),
disablePathNormalizing: false,
},
want: "http://bar.example.com/def",
},
{
name: "Path normalizing enabled, special characters in path",
args: args{
baseURL: "http://foo.example.com/abc/*/def",
location: []byte("http://bar.example.com/123/*/456"),
disablePathNormalizing: false,
},
want: "http://bar.example.com/123/%2A/456",
},
{
name: "Path normalizing disabled, no special characters in path",
args: args{
baseURL: "http://foo.example.com/abc",
location: []byte("http://bar.example.com/def"),
disablePathNormalizing: true,
},
want: "http://bar.example.com/def",
},
{
name: "Path normalizing disabled, special characters in path",
args: args{
baseURL: "http://foo.example.com/abc/*/def",
location: []byte("http://bar.example.com/123/*/456"),
disablePathNormalizing: true,
},
want: "http://bar.example.com/123/*/456",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := getRedirectURL(tt.args.baseURL, tt.args.location, tt.args.disablePathNormalizing); got != tt.want {
t.Errorf("getRedirectURL() = %v, want %v", got, tt.want)
}
})
}
}
7 changes: 7 additions & 0 deletions http.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ type Request struct {

// Use Host header (request.Header.SetHost) instead of the host from SetRequestURI, SetHost, or URI().SetHost
UseHostHeader bool

// DisableRedirectPathNormalizing disables redirect path normalization when used with DoRedirects.
//
// By default redirect path values are normalized, i.e.
// extra slashes are removed, special characters are encoded.
DisableRedirectPathNormalizing bool
}

// Response represents HTTP response.
Expand Down Expand Up @@ -1080,6 +1086,7 @@ func (req *Request) Reset() {
req.resetSkipHeader()
req.timeout = 0
req.UseHostHeader = false
req.DisableRedirectPathNormalizing = false
}

func (req *Request) resetSkipHeader() {
Expand Down
Loading