package api import ( "database/sql" "errors" "net/http" "github.com/gin-gonic/gin" "github.com/hermeznetwork/hermez-node/db/historydb" "github.com/hermeznetwork/hermez-node/log" "github.com/hermeznetwork/hermez-node/metric" "github.com/hermeznetwork/tracerr" "github.com/lib/pq" "github.com/russross/meddler" ) const ( // maxLimit is the max permitted items to be returned in paginated responses maxLimit uint = 2049 // dfltOrder indicates how paginated endpoints are ordered if not specified dfltOrder = historydb.OrderAsc // dfltLimit indicates the limit of returned items in paginated responses if the query param limit is not provided dfltLimit uint = 20 // 2^32 -1 maxUint32 = 4294967295 // 2^64 /2 -1 maxInt64 = 9223372036854775807 // Error for duplicated key errDuplicatedKey = "Item already exists" // Error for timeout due to SQL connection errSQLTimeout = "The node is under heavy preasure, please try again later" // Error message returned when context reaches timeout errCtxTimeout = "context deadline exceeded" ) var ( // ErrNilBidderAddr is used when a nil bidderAddr is received in the getCoordinator method ErrNilBidderAddr = errors.New("biderAddr can not be nil") ) func retSQLErr(err error, c *gin.Context) { log.Warnw("HTTP API SQL request error", "err", err) unwrapErr := tracerr.Unwrap(err) metric.CollectError(unwrapErr) errMsg := unwrapErr.Error() retDupKey := func(errCode pq.ErrorCode) { // https://www.postgresql.org/docs/current/errcodes-appendix.html if errCode == "23505" { c.JSON(http.StatusInternalServerError, errorMsg{ Message: errDuplicatedKey, }) } else { c.JSON(http.StatusInternalServerError, errorMsg{ Message: errMsg, }) } } if errMsg == errCtxTimeout { c.JSON(http.StatusServiceUnavailable, errorMsg{ Message: errSQLTimeout, }) } else if sqlErr, ok := tracerr.Unwrap(err).(*pq.Error); ok { retDupKey(sqlErr.Code) } else if sqlErr, ok := meddler.DriverErr(tracerr.Unwrap(err)); ok { retDupKey(sqlErr.(*pq.Error).Code) } else if tracerr.Unwrap(err) == sql.ErrNoRows { c.JSON(http.StatusNotFound, errorMsg{ Message: errMsg, }) } else { c.JSON(http.StatusInternalServerError, errorMsg{ Message: errMsg, }) } } func retBadReq(err error, c *gin.Context) { log.Warnw("HTTP API Bad request error", "err", err) metric.CollectError(err) c.JSON(http.StatusBadRequest, errorMsg{ Message: err.Error(), }) }