github.com/openfga/openfga@v1.5.4-rc1/pkg/middleware/recovery/recovery.go (about) 1 package recovery 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "net/http" 8 9 grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" 10 11 "go.uber.org/zap" 12 "google.golang.org/grpc/codes" 13 "google.golang.org/grpc/status" 14 15 openfgav1 "github.com/openfga/api/proto/openfga/v1" 16 17 "github.com/openfga/openfga/pkg/logger" 18 "github.com/openfga/openfga/pkg/server/errors" 19 ) 20 21 // HTTPPanicRecoveryHandler recover from panic for http services. 22 func HTTPPanicRecoveryHandler(next http.Handler, logger logger.Logger) http.Handler { 23 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 24 defer func() { 25 if err := recover(); err != nil { 26 logger.Error("HTTPPanicRecoveryHandler has recovered a panic", zap.Error(fmt.Errorf("%v", err))) 27 w.Header().Set("content-type", "application/json") 28 w.WriteHeader(http.StatusInternalServerError) 29 30 responseBody, err := json.Marshal(map[string]string{ 31 "code": openfgav1.InternalErrorCode_internal_error.String(), 32 "message": errors.InternalServerErrorMsg, 33 }) 34 if err != nil { 35 http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) 36 return 37 } 38 39 _, err = w.Write(responseBody) 40 if err != nil { 41 http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) 42 } 43 } 44 }() 45 next.ServeHTTP(w, r) 46 }) 47 } 48 49 // PanicRecoveryHandler recovers from panics for unary/stream services. 50 func PanicRecoveryHandler(logger logger.Logger) grpc_recovery.RecoveryHandlerFuncContext { 51 return func(ctx context.Context, p any) error { 52 logger.Error("PanicRecoveryHandler has recovered a panic", 53 zap.Error(fmt.Errorf("%v", p))) 54 55 return status.Errorf(codes.Internal, errors.InternalServerErrorMsg) 56 } 57 }