From 80f3a0647f0ceb1b82979a063d98d5f6f741b76d Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 19 Jul 2019 16:50:37 +0200 Subject: [PATCH] rpc: add HTTP status code to handshake error This makes it easier to debug failing connections. --- rpc/websocket.go | 21 +++++++++++++++++++-- rpc/websocket_test.go | 5 ++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/rpc/websocket.go b/rpc/websocket.go index 538b38e7f6..1632d6af41 100644 --- a/rpc/websocket.go +++ b/rpc/websocket.go @@ -111,6 +111,19 @@ func wsHandshakeValidator(allowedOrigins []string) func(*http.Request) bool { return f } +type wsHandshakeError struct { + err error + status string +} + +func (e wsHandshakeError) Error() string { + s := e.err.Error() + if e.status != "" { + s += " (HTTP status " + e.status + ")" + } + return s +} + // DialWebsocket creates a new RPC client that communicates with a JSON-RPC server // that is listening on the given endpoint. // @@ -127,9 +140,13 @@ func DialWebsocket(ctx context.Context, endpoint, origin string) (*Client, error WriteBufferPool: wsBufferPool, } return newClient(ctx, func(ctx context.Context) (ServerCodec, error) { - conn, _, err := dialer.DialContext(ctx, endpoint, header) + conn, resp, err := dialer.DialContext(ctx, endpoint, header) if err != nil { - return nil, err + hErr := wsHandshakeError{err: err} + if resp != nil { + hErr.status = resp.Status + } + return nil, hErr } return newWebsocketCodec(conn), nil }) diff --git a/rpc/websocket_test.go b/rpc/websocket_test.go index 4a83ea95ec..a00e8da0f6 100644 --- a/rpc/websocket_test.go +++ b/rpc/websocket_test.go @@ -21,6 +21,7 @@ import ( "net" "net/http" "net/http/httptest" + "reflect" "strings" "testing" "time" @@ -63,10 +64,12 @@ func TestWebsocketOriginCheck(t *testing.T) { client.Close() t.Fatal("no error for wrong origin") } - if err != websocket.ErrBadHandshake { + wantErr := wsHandshakeError{websocket.ErrBadHandshake, "403 Forbidden"} + if !reflect.DeepEqual(err, wantErr) { t.Fatalf("wrong error for wrong origin: %q", err) } + // Connections without origin header should work. client, err = DialWebsocket(context.Background(), wsURL, "") if err != nil { t.Fatal("error for empty origin")