github.com/mundipagg/boleto-api@v0.0.0-20230620145841-3f9ec742599f/api/errors.go (about)

     1  package api
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"runtime/debug"
     7  
     8  	"github.com/gin-gonic/gin"
     9  	"github.com/mundipagg/boleto-api/models"
    10  )
    11  
    12  var validate = map[string]int{
    13  	"MP400":                   http.StatusBadRequest,
    14  	"MPAmountInCents":         http.StatusBadRequest,
    15  	"MPExpireDate":            http.StatusBadRequest,
    16  	"MPBuyerDocumentType":     http.StatusBadRequest,
    17  	"MPDocumentNumber":        http.StatusBadRequest,
    18  	"MPRecipientDocumentType": http.StatusBadRequest,
    19  	"MPTimeout":               http.StatusGatewayTimeout,
    20  	"MPOurNumberFail":         http.StatusBadGateway,
    21  }
    22  
    23  func handleErrors(c *gin.Context) {
    24  	c.Next()
    25  
    26  	var status int
    27  	var exist bool
    28  
    29  	response := getResponseFromContext(c)
    30  
    31  	if !qualifiedForNewErrorHandling(c, response) {
    32  		return
    33  	}
    34  
    35  	bankcode := response.Errors[0].Code
    36  	if status, exist = validate[bankcode]; !exist {
    37  		status = getBankFromContext(c).GetErrorsMap()[bankcode]
    38  	}
    39  
    40  	switch status {
    41  	case http.StatusBadRequest:
    42  		response.Errors[0].Code = "MP400"
    43  		c.JSON(http.StatusBadRequest, response)
    44  	case http.StatusBadGateway:
    45  		response.Errors[0].Code = "MP502"
    46  		c.JSON(http.StatusBadGateway, response)
    47  	case http.StatusGatewayTimeout:
    48  		response.Errors[0].Code = "MP504"
    49  		c.JSON(http.StatusGatewayTimeout, response)
    50  	default:
    51  		response.Errors[0].Code = "MP500"
    52  		clientResponse := getResponseError("MP500", "An internal error occurred.")
    53  		c.JSON(http.StatusInternalServerError, clientResponse)
    54  	}
    55  
    56  	c.Set(responseKey, response)
    57  }
    58  
    59  func qualifiedForNewErrorHandling(c *gin.Context, response models.BoletoResponse) bool {
    60  	if (getBankFromContext(c).GetErrorsMap() != nil && response.HasErrors()) || hasPanic(c) {
    61  		return true
    62  	}
    63  	return false
    64  }
    65  
    66  func hasPanic(c *gin.Context) bool {
    67  	_, exists := c.Get("hasPanic")
    68  
    69  	return exists
    70  }
    71  
    72  func getErrorCodeToLog(c *gin.Context) string {
    73  	response := getResponseFromContext(c)
    74  	if response.HasErrors() {
    75  		return response.Errors[0].ErrorCode()
    76  	}
    77  	return ""
    78  }
    79  
    80  func panicRecoveryHandler(c *gin.Context) {
    81  	defer func() {
    82  		if rec := recover(); rec != nil {
    83  			err := fmt.Errorf("an internal error occurred: %v.\ninner exception: %s", rec, string(debug.Stack()))
    84  
    85  			errorResponse := getResponseError("MP500", err.Error())
    86  
    87  			c.Set(responseKey, errorResponse)
    88  			c.Set("hasPanic", true)
    89  		}
    90  	}()
    91  
    92  	c.Next()
    93  }
    94  
    95  func errorResponseToClient(c *gin.Context) {
    96  	c.Next()
    97  
    98  	if hasPanic(c) {
    99  		errorResponse := getResponseError("MP500", "An internal error occurred.")
   100  
   101  		c.JSON(http.StatusInternalServerError, errorResponse)
   102  	}
   103  }
   104  
   105  func getResponseError(code string, message string) models.BoletoResponse {
   106  	errorResponse := models.BoletoResponse{
   107  		Errors: models.NewErrors(),
   108  	}
   109  
   110  	errorResponse.Errors.Append(code, message)
   111  
   112  	return errorResponse
   113  }