@@ -535,9 +535,8 @@ func (s *Server) handleBatchRequest(ctx context.Context, batchReq []json.RawMess
535535 return nil , finalHeaders , nil
536536 }
537537
538- result , err := json .Marshal (responses )
539-
540- return result , finalHeaders , err // todo: fix batch request aggregate header
538+ // todo: fix batch request aggregate header
539+ return concatBatchResponses (responses ), finalHeaders , nil
541540}
542541
543542func isBatch (reader * bufio.Reader ) bool {
@@ -568,6 +567,27 @@ func isNilOrEmpty(i any) (bool, error) {
568567 }
569568}
570569
570+ // concatBatchResponses builds the JSON array from elements that already valid
571+ // JSON, so it joins bytes instead of re-encoding. json.Marshal would run every
572+ // byte through compact() again, which is costly
573+ func concatBatchResponses (responses []json.RawMessage ) []byte {
574+ size := len (responses ) + 1
575+ for _ , response := range responses {
576+ size += len (response )
577+ }
578+
579+ result := make ([]byte , 0 , size )
580+ result = append (result , '[' )
581+ for i , response := range responses {
582+ if i > 0 {
583+ result = append (result , ',' )
584+ }
585+ result = append (result , response ... )
586+ }
587+
588+ return append (result , ']' )
589+ }
590+
571591// TODO: add recover() to catch panics from handlers/validators and return a JSON-RPC internal error
572592// instead of crashing the HTTP connection
573593func (s * Server ) handleRequest (ctx context.Context , req * Request ) (* response , http.Header , error ) {
0 commit comments