Skip to content

Commit 147a33a

Browse files
committed
- Use faster JSON encode/decode library (goccy/go-json)
- Use faster HTTP library for backend RPC requests
1 parent 48555d8 commit 147a33a

File tree

4 files changed

+102
-29
lines changed

4 files changed

+102
-29
lines changed

proxyd/backend.go

+74-28
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import (
44
"bytes"
55
"context"
66
"crypto/tls"
7-
"encoding/json"
87
"errors"
98
"fmt"
9+
"github.com/goccy/go-json"
10+
"github.com/valyala/fasthttp"
1011
"io"
1112
"math"
1213
"math/rand"
@@ -111,10 +112,19 @@ var (
111112
HTTPErrorCode: 500,
112113
}
113114

115+
ErrBackendResponseDecompressionError = &RPCErr{
116+
Code: JSONRPCErrorInternal - 22,
117+
Message: "backend response too large",
118+
HTTPErrorCode: 500,
119+
}
120+
114121
ErrBackendUnexpectedJSONRPC = errors.New("backend returned an unexpected JSON-RPC response")
115122

116123
ErrConsensusGetReceiptsCantBeBatched = errors.New("consensus_getReceipts cannot be batched")
117124
ErrConsensusGetReceiptsInvalidTarget = errors.New("unsupported consensus_receipts_target")
125+
126+
// For the new fastHTTP client
127+
headerContentTypeJson = []byte("application/json")
118128
)
119129

120130
func ErrInvalidRequest(msg string) *RPCErr {
@@ -141,6 +151,7 @@ type Backend struct {
141151
authUsername string
142152
authPassword string
143153
headers map[string]string
154+
fastClient *fasthttp.Client
144155
client *LimitedHTTPClient
145156
dialer *websocket.Dialer
146157
maxRetries int
@@ -318,12 +329,29 @@ func NewBackend(
318329
rpcSemaphore *semaphore.Weighted,
319330
opts ...BackendOpt,
320331
) *Backend {
332+
readTimeout, _ := time.ParseDuration("10000ms")
333+
writeTimeout, _ := time.ParseDuration("10000ms")
334+
maxIdleConnDuration, _ := time.ParseDuration("1h")
321335
backend := &Backend{
322336
Name: name,
323337
rpcURL: rpcURL,
324338
wsURL: wsURL,
325339
maxResponseSize: math.MaxInt64,
326-
client: &LimitedHTTPClient{
340+
fastClient: &fasthttp.Client{
341+
MaxConnsPerHost: 16384,
342+
ReadTimeout: readTimeout,
343+
WriteTimeout: writeTimeout,
344+
MaxIdleConnDuration: maxIdleConnDuration,
345+
NoDefaultUserAgentHeader: true, // Don't send: User-Agent: fasthttp
346+
DisableHeaderNamesNormalizing: true, // If you set the case on your headers correctly you can enable this
347+
DisablePathNormalizing: true,
348+
// increase DNS cache time to five minutes
349+
Dial: (&fasthttp.TCPDialer{
350+
Concurrency: 32768,
351+
DNSCacheDuration: time.Minute * 5,
352+
}).Dial,
353+
},
354+
client: &LimitedHTTPClient{ // Keep legacy client for now, TODO remove
327355
Client: http.Client{Timeout: 5 * time.Second},
328356
sem: rpcSemaphore,
329357
backendName: name,
@@ -550,21 +578,10 @@ func (b *Backend) doForward(ctx context.Context, rpcReqs []*RPCReq, isBatch bool
550578
body = mustMarshalJSON(rpcReqs)
551579
}
552580

553-
httpReq, err := http.NewRequestWithContext(ctx, "POST", b.rpcURL, bytes.NewReader(body))
554-
if err != nil {
555-
b.intermittentErrorsSlidingWindow.Incr()
556-
RecordBackendNetworkErrorRateSlidingWindow(b, b.ErrorRate())
557-
return nil, wrapErr(err, "error creating backend request")
558-
}
559-
560-
if b.authPassword != "" {
561-
httpReq.SetBasicAuth(b.authUsername, b.authPassword)
562-
}
563-
564-
opTxProxyAuth := GetOpTxProxyAuthHeader(ctx)
565-
if opTxProxyAuth != "" {
566-
httpReq.Header.Set(DefaultOpTxProxyAuthHeader, opTxProxyAuth)
567-
}
581+
req := fasthttp.AcquireRequest()
582+
req.SetRequestURI(b.rpcURL)
583+
req.Header.SetMethod(fasthttp.MethodPost)
584+
req.SetBody(body)
568585

569586
xForwardedFor := GetXForwardedFor(ctx)
570587
if b.stripTrailingXFF {
@@ -573,42 +590,63 @@ func (b *Backend) doForward(ctx context.Context, rpcReqs []*RPCReq, isBatch bool
573590
xForwardedFor = fmt.Sprintf("%s, %s", xForwardedFor, b.proxydIP)
574591
}
575592

576-
httpReq.Header.Set("content-type", "application/json")
577-
httpReq.Header.Set("X-Forwarded-For", xForwardedFor)
593+
req.Header.SetContentTypeBytes(headerContentTypeJson)
594+
req.Header.Set("X-Forwarded-For", xForwardedFor)
595+
596+
// Geth native backend supports gzip
597+
req.Header.Set("Accept-Encoding", "gzip")
578598

579599
for name, value := range b.headers {
580-
httpReq.Header.Set(name, value)
600+
req.Header.Set(name, value)
581601
}
582602

583603
start := time.Now()
584-
httpRes, err := b.client.DoLimited(httpReq)
604+
605+
httpRes := fasthttp.AcquireResponse()
606+
607+
reqTimeout := time.Duration(5000) * time.Millisecond
608+
609+
err := b.fastClient.DoTimeout(req, httpRes, reqTimeout)
585610
if err != nil {
586611
b.intermittentErrorsSlidingWindow.Incr()
587612
RecordBackendNetworkErrorRateSlidingWindow(b, b.ErrorRate())
588-
return nil, wrapErr(err, "error in backend request")
613+
return nil, wrapErr(err, "err in backend request")
589614
}
615+
fasthttp.ReleaseRequest(req)
616+
defer fasthttp.ReleaseResponse(httpRes)
590617

591618
metricLabelMethod := rpcReqs[0].Method
592619
if isBatch {
593620
metricLabelMethod = "<batch>"
594621
}
622+
623+
sc := httpRes.StatusCode()
624+
595625
rpcBackendHTTPResponseCodesTotal.WithLabelValues(
596626
GetAuthCtx(ctx),
597627
b.Name,
598628
metricLabelMethod,
599-
strconv.Itoa(httpRes.StatusCode),
629+
strconv.Itoa(sc),
600630
strconv.FormatBool(isBatch),
601631
).Inc()
602632

603633
// Alchemy returns a 400 on bad JSONs, so handle that case
604-
if httpRes.StatusCode != 200 && httpRes.StatusCode != 400 {
634+
if sc != 200 && sc != 400 {
605635
b.intermittentErrorsSlidingWindow.Incr()
606636
RecordBackendNetworkErrorRateSlidingWindow(b, b.ErrorRate())
607637
return nil, fmt.Errorf("response code %d", httpRes.StatusCode)
608638
}
609639

610-
defer httpRes.Body.Close()
611-
resB, err := io.ReadAll(LimitReader(httpRes.Body, b.maxResponseSize))
640+
// defer httpRes.Body.Close()
641+
642+
// This should intelligently choose decompression based on whether the downstream
643+
// backend supported our request or not.
644+
bodyUncomp, err := httpRes.BodyUncompressed()
645+
if err != nil {
646+
return nil, ErrBackendResponseDecompressionError
647+
}
648+
649+
resB, err := io.ReadAll(LimitReader(bytes.NewReader(bodyUncomp), b.maxResponseSize))
612650
if errors.Is(err, ErrLimitReaderOverLimit) {
613651
return nil, ErrBackendResponseTooLarge
614652
}
@@ -649,9 +687,9 @@ func (b *Backend) doForward(ctx context.Context, rpcReqs []*RPCReq, isBatch bool
649687

650688
// capture the HTTP status code in the response. this will only
651689
// ever be 400 given the status check on line 318 above.
652-
if httpRes.StatusCode != 200 {
690+
if sc != 200 {
653691
for _, res := range rpcRes {
654-
res.Error.HTTPErrorCode = httpRes.StatusCode
692+
res.Error.HTTPErrorCode = sc
655693
}
656694
}
657695
duration := time.Since(start)
@@ -1423,6 +1461,14 @@ func (bg *BackendGroup) ForwardRequestToBackendGroup(
14231461
error: err,
14241462
}
14251463
}
1464+
1465+
if errors.Is(err, ErrBackendResponseDecompressionError) {
1466+
return &BackendGroupRPCResponse{
1467+
RPCRes: nil,
1468+
ServedBy: "",
1469+
error: err,
1470+
}
1471+
}
14261472
if errors.Is(err, ErrBackendOffline) {
14271473
log.Warn(
14281474
"skipping offline backend",

proxyd/go.mod

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ require (
88
github.com/emirpasic/gods v1.18.1
99
github.com/ethereum/go-ethereum v1.14.8
1010
github.com/go-redsync/redsync/v4 v4.10.0
11+
github.com/goccy/go-json v0.10.2
1112
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb
1213
github.com/gorilla/mux v1.8.0
1314
github.com/gorilla/websocket v1.5.0
@@ -18,6 +19,7 @@ require (
1819
github.com/rs/cors v1.11.0
1920
github.com/stretchr/testify v1.9.0
2021
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
22+
github.com/valyala/fasthttp v1.40.0
2123
github.com/xaionaro-go/weightedshuffle v0.0.0-20211213010739-6a74fbc7d24a
2224
golang.org/x/sync v0.7.0
2325
gopkg.in/yaml.v3 v3.0.1
@@ -28,6 +30,7 @@ require (
2830
github.com/Microsoft/go-winio v0.6.2 // indirect
2931
github.com/VictoriaMetrics/fastcache v1.12.2 // indirect
3032
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 // indirect
33+
github.com/andybalholm/brotli v1.0.5 // indirect
3134
github.com/beorn7/perks v1.0.1 // indirect
3235
github.com/bits-and-blooms/bitset v1.10.0 // indirect
3336
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
@@ -74,6 +77,7 @@ require (
7477
github.com/supranational/blst v0.3.11 // indirect
7578
github.com/tklauser/go-sysconf v0.3.12 // indirect
7679
github.com/tklauser/numcpus v0.6.1 // indirect
80+
github.com/valyala/bytebufferpool v1.0.0 // indirect
7781
github.com/yuin/gopher-lua v1.1.0 // indirect
7882
github.com/yusufpapurcu/wmi v1.2.3 // indirect
7983
golang.org/x/crypto v0.22.0 // indirect

proxyd/go.sum

+23
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j
1212
github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
1313
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
1414
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
15+
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
16+
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
17+
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
1518
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
1619
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
1720
github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88=
@@ -88,6 +91,8 @@ github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F4
8891
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
8992
github.com/go-redsync/redsync/v4 v4.10.0 h1:hTeAak4C73mNBQSTq6KCKDFaiIlfC+z5yTTl8fCJuBs=
9093
github.com/go-redsync/redsync/v4 v4.10.0/go.mod h1:ZfayzutkgeBmEmBlUR3j+rF6kN44UUGtEdfzhBFZTPc=
94+
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
95+
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
9196
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
9297
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
9398
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
@@ -128,6 +133,7 @@ github.com/holiman/uint256 v1.3.1/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXei
128133
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
129134
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
130135
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
136+
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
131137
github.com/klauspost/compress v1.17.1 h1:NE3C767s2ak2bweCZo3+rdP4U/HoyVXLv/X9f2gPS5g=
132138
github.com/klauspost/compress v1.17.1/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
133139
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@@ -201,6 +207,11 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA
201207
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
202208
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
203209
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
210+
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
211+
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
212+
github.com/valyala/fasthttp v1.40.0 h1:CRq/00MfruPGFLTQKY8b+8SfdK60TxNztjRMnH0t1Yc=
213+
github.com/valyala/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
214+
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
204215
github.com/xaionaro-go/weightedshuffle v0.0.0-20211213010739-6a74fbc7d24a h1:WS5nQycV+82Ndezq0UcMcGVG416PZgcJPqI/bLM824A=
205216
github.com/xaionaro-go/weightedshuffle v0.0.0-20211213010739-6a74fbc7d24a/go.mod h1:0KAUfC65le2kMu4fnBxm7Xj3PkQ3MBpJbF5oMmqufBc=
206217
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -212,6 +223,7 @@ github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQ
212223
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
213224
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
214225
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
226+
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
215227
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
216228
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
217229
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
@@ -225,6 +237,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
225237
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
226238
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
227239
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
240+
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
241+
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
228242
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
229243
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
230244
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -244,15 +258,24 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
244258
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
245259
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
246260
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
261+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
262+
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
263+
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
264+
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
265+
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
247266
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
248267
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
249268
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
250269
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
251270
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
252271
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
272+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
273+
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
253274
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
254275
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
255276
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
277+
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
278+
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
256279
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
257280
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
258281
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

proxyd/rpc.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package proxyd
22

33
import (
4-
"encoding/json"
4+
"github.com/goccy/go-json"
55
"io"
66
"strings"
77
)

0 commit comments

Comments
 (0)