github.com/aldelo/common@v1.5.1/wrapper/gin/ginrecover.go (about)

     1  package gin
     2  
     3  /*
     4   * Copyright 2020-2023 Aldelo, LP
     5   *
     6   * Licensed under the Apache License, Version 2.0 (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   *     http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  import (
    20  	"fmt"
    21  	"github.com/gin-gonic/gin"
    22  	"github.com/go-errors/errors"
    23  	"io"
    24  	"log"
    25  	"net/http/httputil"
    26  )
    27  
    28  // NiceRecovery replaces default recovery, with custom content,
    29  // to be called via gin.New() right after object init
    30  //
    31  // Credit: code based and revised from github.com/ekyoung/gin-nice-recovery
    32  func NiceRecovery(f func(c *gin.Context, err interface{})) gin.HandlerFunc {
    33  	return NiceRecoveryWithWriter(f, gin.DefaultErrorWriter)
    34  }
    35  
    36  // NiceRecoveryWithWriter replaces default recovery, with custom content,
    37  // to be called via gin.New() right after object init
    38  //
    39  // Credit: code based and revised from github.com/ekyoung/gin-nice-recovery
    40  func NiceRecoveryWithWriter(f func(c *gin.Context, err interface{}), out io.Writer) gin.HandlerFunc {
    41  	var logger *log.Logger
    42  
    43  	if out != nil {
    44  		logger = log.New(out, "\n\n\x1b[31m", log.LstdFlags)
    45  	}
    46  
    47  	return func(c *gin.Context) {
    48  		defer func() {
    49  			if err := recover(); err != nil {
    50  				if logger != nil {
    51  					httpRequest, _ := httputil.DumpRequest(c.Request, false)
    52  					goErr := errors.Wrap(err, 3)
    53  					reset := string([]byte{27, 91, 48, 109})
    54  					logger.Printf(fmt.Sprintf("[Recovery] Panic Recovered:\n\n%s %s\n\n%s%s", httpRequest, goErr.Error(), goErr.Stack(), reset))
    55  				}
    56  
    57  				f(c, fmt.Errorf("Internal Server Error"))
    58  			}
    59  		}()
    60  
    61  		c.Next() // execute all the handlers
    62  	}
    63  }