rpc: add separate size limit for websocket (#22385)

This makes the WebSocket message size limit independent of the
limit used for HTTP requests. The new limit for WebSocket messages 
is 15MB.
pull/22386/head
Felix Lange 4 years ago committed by GitHub
parent dc109cce26
commit 27b31371d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      rpc/http_test.go
  2. 10
      rpc/testservice_test.go
  3. 3
      rpc/websocket.go
  4. 27
      rpc/websocket_test.go

@ -98,3 +98,28 @@ func confirmHTTPRequestYieldsStatusCode(t *testing.T, method, contentType, body
func TestHTTPResponseWithEmptyGet(t *testing.T) { func TestHTTPResponseWithEmptyGet(t *testing.T) {
confirmHTTPRequestYieldsStatusCode(t, http.MethodGet, "", "", http.StatusOK) confirmHTTPRequestYieldsStatusCode(t, http.MethodGet, "", "", http.StatusOK)
} }
// This checks that maxRequestContentLength is not applied to the response of a request.
func TestHTTPRespBodyUnlimited(t *testing.T) {
const respLength = maxRequestContentLength * 3
s := NewServer()
defer s.Stop()
s.RegisterName("test", largeRespService{respLength})
ts := httptest.NewServer(s)
defer ts.Close()
c, err := DialHTTP(ts.URL)
if err != nil {
t.Fatal(err)
}
defer c.Close()
var r string
if err := c.Call(&r, "test_largeResp"); err != nil {
t.Fatal(err)
}
if len(r) != respLength {
t.Fatalf("response has wrong length %d, want %d", len(r), respLength)
}
}

@ -20,6 +20,7 @@ import (
"context" "context"
"encoding/binary" "encoding/binary"
"errors" "errors"
"strings"
"sync" "sync"
"time" "time"
) )
@ -194,3 +195,12 @@ func (s *notificationTestService) HangSubscription(ctx context.Context, val int)
}() }()
return subscription, nil return subscription, nil
} }
// largeRespService generates arbitrary-size JSON responses.
type largeRespService struct {
length int
}
func (x largeRespService) LargeResp() string {
return strings.Repeat("x", x.length)
}

@ -37,6 +37,7 @@ const (
wsWriteBuffer = 1024 wsWriteBuffer = 1024
wsPingInterval = 60 * time.Second wsPingInterval = 60 * time.Second
wsPingWriteTimeout = 5 * time.Second wsPingWriteTimeout = 5 * time.Second
wsMessageSizeLimit = 15 * 1024 * 1024
) )
var wsBufferPool = new(sync.Pool) var wsBufferPool = new(sync.Pool)
@ -239,7 +240,7 @@ type websocketCodec struct {
} }
func newWebsocketCodec(conn *websocket.Conn) ServerCodec { func newWebsocketCodec(conn *websocket.Conn) ServerCodec {
conn.SetReadLimit(maxRequestContentLength) conn.SetReadLimit(wsMessageSizeLimit)
wc := &websocketCodec{ wc := &websocketCodec{
jsonCodec: NewFuncCodec(conn, conn.WriteJSON, conn.ReadJSON).(*jsonCodec), jsonCodec: NewFuncCodec(conn, conn.WriteJSON, conn.ReadJSON).(*jsonCodec),
conn: conn, conn: conn,

@ -157,6 +157,33 @@ func TestClientWebsocketPing(t *testing.T) {
} }
} }
// This checks that the websocket transport can deal with large messages.
func TestClientWebsocketLargeMessage(t *testing.T) {
var (
srv = NewServer()
httpsrv = httptest.NewServer(srv.WebsocketHandler(nil))
wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:")
)
defer srv.Stop()
defer httpsrv.Close()
respLength := wsMessageSizeLimit - 50
srv.RegisterName("test", largeRespService{respLength})
c, err := DialWebsocket(context.Background(), wsURL, "")
if err != nil {
t.Fatal(err)
}
var r string
if err := c.Call(&r, "test_largeResp"); err != nil {
t.Fatal("call failed:", err)
}
if len(r) != respLength {
t.Fatalf("response has wrong length %d, want %d", len(r), respLength)
}
}
// wsPingTestServer runs a WebSocket server which accepts a single subscription request. // wsPingTestServer runs a WebSocket server which accepts a single subscription request.
// When a value arrives on sendPing, the server sends a ping frame, waits for a matching // When a value arrives on sendPing, the server sends a ping frame, waits for a matching
// pong and finally delivers a single subscription result. // pong and finally delivers a single subscription result.

Loading…
Cancel
Save