diff --git a/internal/httputil/http.go b/internal/httputil/http.go index ba2cc0284..ee6370bd1 100644 --- a/internal/httputil/http.go +++ b/internal/httputil/http.go @@ -71,13 +71,13 @@ func PostJSON[reqtype, restype any, errtype error]( return err } if res.StatusCode != http.StatusOK { - var errorBody errtype - if msgerr := json.NewDecoder(res.Body).Decode(&errorBody); msgerr != nil { - return fmt.Errorf("internal API: %d from %s", res.StatusCode, apiURL) + errorBody := new(errtype) + if err = json.NewDecoder(res.Body).Decode(errorBody); err != nil { + return fmt.Errorf("HTTP %d from %s", res.StatusCode, apiURL) } - return errorBody + return *errorBody } - if err := json.NewDecoder(res.Body).Decode(response); err != nil { + if err = json.NewDecoder(res.Body).Decode(response); err != nil { return fmt.Errorf("json.NewDecoder.Decode: %w", err) } return nil diff --git a/internal/httputil/internalapi.go b/internal/httputil/internalapi.go index 5dcc596cc..fea7ff188 100644 --- a/internal/httputil/internalapi.go +++ b/internal/httputil/internalapi.go @@ -17,12 +17,23 @@ package httputil import ( "context" "encoding/json" + "fmt" "net/http" + "reflect" "github.com/matrix-org/util" opentracing "github.com/opentracing/opentracing-go" ) +type InternalAPIError struct { + Type string + Message string +} + +func (e InternalAPIError) Error() string { + return fmt.Sprintf("internal API returned %q error: %s", e.Type, e.Message) +} + func MakeInternalRPCAPI[reqtype, restype any](metricsName string, f func(context.Context, *reqtype, *restype) error) http.Handler { return MakeInternalAPI(metricsName, func(req *http.Request) util.JSONResponse { var request reqtype @@ -31,9 +42,18 @@ func MakeInternalRPCAPI[reqtype, restype any](metricsName string, f func(context return util.MessageResponse(http.StatusBadRequest, err.Error()) } if err := f(req.Context(), &request, &response); err != nil { - return util.ErrorResponse(err) + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: &InternalAPIError{ + Type: reflect.TypeOf(err).String(), + Message: fmt.Sprintf("%s", err), + }, + } + } + return util.JSONResponse{ + Code: http.StatusOK, + JSON: &response, } - return util.JSONResponse{Code: http.StatusOK, JSON: &response} }) } @@ -45,9 +65,18 @@ func MakeInternalProxyAPI[reqtype, restype any](metricsName string, f func(conte } response, err := f(req.Context(), &request) if err != nil { - return util.ErrorResponse(err) + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: &InternalAPIError{ + Type: reflect.TypeOf(err).String(), + Message: fmt.Sprintf("%s", err), + }, + } + } + return util.JSONResponse{ + Code: http.StatusOK, + JSON: response, } - return util.JSONResponse{Code: http.StatusOK, JSON: response} }) } @@ -55,7 +84,7 @@ func CallInternalRPCAPI[req, res any](name, url string, client *http.Client, ctx span, ctx := opentracing.StartSpanFromContext(ctx, name) defer span.Finish() - return PostJSON[req, res, error](ctx, span, client, url, request, response) + return PostJSON[req, res, InternalAPIError](ctx, span, client, url, request, response) } func CallInternalProxyAPI[req, res any, errtype error](name, url string, client *http.Client, ctx context.Context, request *req) (res, error) {