mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-03 11:45:18 +00:00
* rpc/jsonrpc/server: return an error in WriteRPCResponseHTTP(Error) (#6204)
instead of panicking
Closes #5529
(cherry picked from commit 00b9524168)
# Conflicts:
# CHANGELOG_PENDING.md
# rpc/jsonrpc/server/http_json_handler.go
# rpc/jsonrpc/server/http_server.go
# rpc/jsonrpc/server/http_server_test.go
# rpc/jsonrpc/server/http_uri_handler.go
* resolve conflicts
* fix linting
* fix conflict
Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
Co-authored-by: Marko Baricevic <marbar3778@yahoo.com>
This commit is contained in:
@@ -89,30 +89,32 @@ func ServeTLS(
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteRPCResponseHTTPError marshals res as JSON and writes it to w.
|
||||
// WriteRPCResponseHTTPError marshals res as JSON (with indent) and writes it
|
||||
// to w.
|
||||
//
|
||||
// Panics if it can't Marshal res or write to w.
|
||||
// source: https://www.jsonrpc.org/historical/json-rpc-over-http.html
|
||||
func WriteRPCResponseHTTPError(
|
||||
w http.ResponseWriter,
|
||||
httpCode int,
|
||||
res types.RPCResponse,
|
||||
) {
|
||||
) error {
|
||||
if res.Error == nil {
|
||||
panic("tried to write http error response without RPC error")
|
||||
}
|
||||
|
||||
jsonBytes, err := json.MarshalIndent(res, "", " ")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return fmt.Errorf("json marshal: %w", err)
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(httpCode)
|
||||
if _, err := w.Write(jsonBytes); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = w.Write(jsonBytes)
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteRPCResponseHTTP marshals res as JSON and writes it to w.
|
||||
//
|
||||
// Panics if it can't Marshal res or write to w.
|
||||
func WriteRPCResponseHTTP(w http.ResponseWriter, res ...types.RPCResponse) {
|
||||
// WriteRPCResponseHTTP marshals res as JSON (with indent) and writes it to w.
|
||||
func WriteRPCResponseHTTP(w http.ResponseWriter, res ...types.RPCResponse) error {
|
||||
var v interface{}
|
||||
if len(res) == 1 {
|
||||
v = res[0]
|
||||
@@ -122,13 +124,12 @@ func WriteRPCResponseHTTP(w http.ResponseWriter, res ...types.RPCResponse) {
|
||||
|
||||
jsonBytes, err := json.MarshalIndent(v, "", " ")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return fmt.Errorf("json marshal: %w", err)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(200)
|
||||
if _, err := w.Write(jsonBytes); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = w.Write(jsonBytes)
|
||||
return err
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -166,7 +167,9 @@ func RecoverAndLogHandler(handler http.Handler, logger log.Logger) http.Handler
|
||||
|
||||
// If RPCResponse
|
||||
if res, ok := e.(types.RPCResponse); ok {
|
||||
WriteRPCResponseHTTP(rww, res)
|
||||
if wErr := WriteRPCResponseHTTP(rww, res); wErr != nil {
|
||||
logger.Error("failed to write response", "res", res, "err", wErr)
|
||||
}
|
||||
} else {
|
||||
// Panics can contain anything, attempt to normalize it as an error.
|
||||
var err error
|
||||
@@ -180,15 +183,12 @@ func RecoverAndLogHandler(handler http.Handler, logger log.Logger) http.Handler
|
||||
default:
|
||||
}
|
||||
|
||||
logger.Error(
|
||||
"Panic in RPC HTTP handler", "err", e, "stack",
|
||||
string(debug.Stack()),
|
||||
)
|
||||
WriteRPCResponseHTTPError(
|
||||
rww,
|
||||
http.StatusInternalServerError,
|
||||
types.RPCInternalError(types.JSONRPCIntID(-1), err),
|
||||
)
|
||||
logger.Error("panic in RPC HTTP handler", "err", e, "stack", string(debug.Stack()))
|
||||
|
||||
res := types.RPCInternalError(types.JSONRPCIntID(-1), err)
|
||||
if wErr := WriteRPCResponseHTTPError(rww, http.StatusInternalServerError, res); wErr != nil {
|
||||
logger.Error("failed to write response", "res", res, "err", wErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user