Skip to content

Commit e3805a2

Browse files
millkendustinxie
authored andcommitted
[API] add batch size limit for jsonrpc (#3805)
* add batch size limit for jsonrpc
1 parent 83008ed commit e3805a2

File tree

2 files changed

+28
-5
lines changed

2 files changed

+28
-5
lines changed

api/types/types.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
package apitypes
22

33
import (
4+
"encoding/json"
5+
"errors"
6+
47
"github.com/iotexproject/iotex-core/action"
58
"github.com/iotexproject/iotex-core/blockchain/block"
69
)
710

11+
// MaxResponseSize is the max size of response
12+
var MaxResponseSize = 1024 * 1024 * 100 // 100MB
13+
814
type (
915
// Web3ResponseWriter is writer for web3 request
1016
Web3ResponseWriter interface {
@@ -49,21 +55,30 @@ func (w *responseWriter) Write(in interface{}) error {
4955

5056
// BatchWriter for multiple web3 requests
5157
type BatchWriter struct {
52-
writer Web3ResponseWriter
53-
buf []interface{}
58+
totalSize int
59+
writer Web3ResponseWriter
60+
buf []json.RawMessage
5461
}
5562

5663
// NewBatchWriter returns a new BatchWriter
5764
func NewBatchWriter(singleWriter Web3ResponseWriter) *BatchWriter {
5865
return &BatchWriter{
59-
writer: singleWriter,
60-
buf: make([]interface{}, 0),
66+
writer: singleWriter,
67+
buf: make([]json.RawMessage, 0),
6168
}
6269
}
6370

6471
// Write adds data into batch buffer
6572
func (w *BatchWriter) Write(in interface{}) error {
66-
w.buf = append(w.buf, in)
73+
raw, err := json.Marshal(in)
74+
if err != nil {
75+
return err
76+
}
77+
w.totalSize += len(raw)
78+
if w.totalSize > MaxResponseSize {
79+
return errors.New("response size exceeds limit")
80+
}
81+
w.buf = append(w.buf, raw)
6782
return nil
6883
}
6984

api/web3server_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/stretchr/testify/require"
1616
"github.com/tidwall/gjson"
1717

18+
apitypes "github.com/iotexproject/iotex-core/api/types"
1819
"github.com/iotexproject/iotex-core/test/mock/mock_apicoreservice"
1920
)
2021

@@ -105,6 +106,13 @@ func TestHandlePost(t *testing.T) {
105106
require.True(gjson.Valid(string(bodyBytes5)))
106107
require.Equal(2, len(gjson.Parse(string(bodyBytes5)).Array()))
107108

109+
// multiple web3 req with big batch
110+
apitypes.MaxResponseSize = 1024 * 1024 // fake max response size
111+
request8, _ := http.NewRequest(http.MethodPost, "http://url.com", strings.NewReader(`[`+strings.Repeat(`{"jsonrpc":"2.0","method":"eth_mining","params":[],"id":1},`, 100000)+`{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":2}]`))
112+
response8 := getServerResp(svr, request8)
113+
bodyBytes8, _ := io.ReadAll(response8.Body)
114+
require.Equal(len(bodyBytes8), 0)
115+
108116
// multiple web3 req2
109117
request6, _ := http.NewRequest(http.MethodPost, "http://url.com", strings.NewReader(`[{"jsonrpc":"2.0","method":"eth_mining","params":[],"id":1}]`))
110118
response6 := getServerResp(svr, request6)

0 commit comments

Comments
 (0)