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  }