Skip to content
Open
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: 5 additions & 0 deletions dial.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"context"
"crypto/rand"
"encoding/base64"
"errors"
"fmt"
"io"
"net/http"
Expand Down Expand Up @@ -97,6 +98,10 @@ func (opts *DialOptions) cloneWithDefaults(ctx context.Context) (context.Context
if oldCheckRedirect != nil {
return oldCheckRedirect(req, via)
}
// net/http only applies its default limit when CheckRedirect is nil.
if len(via) >= 10 {
return errors.New("stopped after 10 redirects")
}
return nil
}
o.HTTPClient = &newClient
Expand Down
27 changes: 27 additions & 0 deletions dial_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,33 @@ func TestDialRedirect(t *testing.T) {
assert.Contains(t, err, "failed to WebSocket dial: WebSocket protocol violation: Upgrade header \"meow\" does not contain websocket")
}

func TestDialRedirectLimit(t *testing.T) {
t.Parallel()

ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()

var requests int
_, _, err := websocket.Dial(ctx, "ws://example.com", &websocket.DialOptions{
HTTPClient: mockHTTPClient(func(r *http.Request) (*http.Response, error) {
requests++
resp := &http.Response{
Header: http.Header{},
Body: http.NoBody,
}
if requests > 20 { // Bound the test if the limit is missing.
resp.StatusCode = http.StatusNotFound
return resp, nil
}
resp.Header.Set("Location", "wss://example.com")
resp.StatusCode = http.StatusFound
return resp, nil
}),
})
assert.Contains(t, err, "stopped after 10 redirects")
assert.Equal(t, "requests", 10, requests)
}

type forwardProxy struct {
hc *http.Client
}
Expand Down
Loading