initial commit 2
This commit is contained in:
130
server/router/routeutils/request.go
Normal file
130
server/router/routeutils/request.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package routeutils
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"strings"
|
||||
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||
"github.com/labstack/echo"
|
||||
)
|
||||
|
||||
// GetAndValidateIntParam gets the integer param value and validates it, returning a validation error in case it's invalid
|
||||
func GetAndValidateIntParam(c echo.Context, paramName string, errorMessage string) (ID int64, err error) {
|
||||
IDstr := c.Param(paramName)
|
||||
|
||||
if strings.TrimSpace(IDstr) == "" {
|
||||
err = errors.NewValidationError(paramName, errorMessage)
|
||||
}
|
||||
|
||||
ID, err = strconv.ParseInt(IDstr, 10, 64)
|
||||
if ID == 0 {
|
||||
err = errors.NewValidationError(paramName, errorMessage)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetAndValidateIntQueryParam gets the integer param value and validates it, returning a validation error in case it's invalid
|
||||
func GetAndValidateIntQueryParam(c echo.Context, paramName string, errorMessage string) (ID int64, err error) {
|
||||
IDstr := c.QueryParam(paramName)
|
||||
|
||||
if strings.TrimSpace(IDstr) == "" {
|
||||
err = errors.NewValidationError(paramName, errorMessage)
|
||||
}
|
||||
|
||||
ID, err = strconv.ParseInt(IDstr, 10, 64)
|
||||
if ID == 0 {
|
||||
err = errors.NewValidationError(paramName, errorMessage)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetAndValidateFloatParam gets the integer param value and validates it, returning a validation error in case it's invalid
|
||||
func GetAndValidateFloatQueryParam(c echo.Context, paramName string, errorMessage string) (ID float64, err error) {
|
||||
IDstr := c.QueryParam(paramName)
|
||||
|
||||
if strings.TrimSpace(IDstr) == "" {
|
||||
err = errors.NewValidationError(paramName, errorMessage)
|
||||
}
|
||||
|
||||
ID, err = strconv.ParseFloat(IDstr, 64)
|
||||
if ID == 0 {
|
||||
err = errors.NewValidationError(paramName, errorMessage)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetAndValidateStringQueryParam gets the integer param value and validates it, returning a validation error in case it's invalid
|
||||
func GetAndValidateStringQueryParam(c echo.Context, paramName string, errorMessage string) (ID string, err error) {
|
||||
ID = c.QueryParam(paramName)
|
||||
|
||||
if strings.TrimSpace(ID) == "" {
|
||||
err = errors.NewValidationError(paramName, errorMessage)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetAndValidateStringParam gets the string param value and validates it, returning a validation error in case it's invalid
|
||||
func GetAndValidateStringParam(c echo.Context, paramName string, errorMessage string) (ID string, err error) {
|
||||
ID = c.Param(paramName)
|
||||
|
||||
if strings.TrimSpace(ID) == "" {
|
||||
err = errors.NewValidationError(paramName, errorMessage)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetPagingParams gets the standard paging params from the URL, returning a validation error in case it's invalid
|
||||
func GetPagingParams(c echo.Context) (page int64, quantity int64) {
|
||||
pg := c.QueryParam("page")
|
||||
ipp := c.QueryParam("quantity")
|
||||
|
||||
page, _ = strconv.ParseInt(pg, 10, 64)
|
||||
quantity, _ = strconv.ParseInt(ipp, 10, 64)
|
||||
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
if quantity < 1 || quantity > 1000 {
|
||||
quantity = 10
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetMultipleQueryParam returns a list of values for multiple query params
|
||||
func GetMultipleQueryParam(c echo.Context, paramName string) (retVal []string) {
|
||||
retVal = make([]string, 0)
|
||||
|
||||
for k, param := range map[string][]string(c.QueryParams()) {
|
||||
if k == paramName {
|
||||
for _, value := range param {
|
||||
retVal = append(retVal, value)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return retVal
|
||||
}
|
||||
|
||||
// GetMultipleIntQueryParam returns a list of integer values from multiple query params
|
||||
func GetMultipleIntQueryParam(c echo.Context, paramName string) (retVal []int64, err error) {
|
||||
retVal = make([]int64, 0)
|
||||
|
||||
for _, value := range GetMultipleQueryParam(c, paramName) {
|
||||
intValue, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil {
|
||||
return retVal, errors.Wrap(err)
|
||||
}
|
||||
retVal = append(retVal, intValue)
|
||||
}
|
||||
|
||||
return retVal, nil
|
||||
}
|
||||
204
server/router/routeutils/response.go
Normal file
204
server/router/routeutils/response.go
Normal file
@@ -0,0 +1,204 @@
|
||||
package routeutils
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/go-sql-driver/mysql"
|
||||
"github.com/labstack/echo"
|
||||
)
|
||||
|
||||
// resultWrapper has fields for standard message responses
|
||||
type resultWrapper struct {
|
||||
Error bool `json:"error,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Redirect bool `json:"redirect,omitempty"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
// ResponseNoContent returns a standard API success with no content response
|
||||
func ResponseNoContent(c echo.Context, data interface{}) error {
|
||||
return c.NoContent(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// ResponseAPIOK returns a standard API success response
|
||||
func ResponseAPIOK(c echo.Context, data interface{}) error {
|
||||
return c.JSON(http.StatusOK, data)
|
||||
}
|
||||
|
||||
// ResponseAPIError returns a standard API error to the response
|
||||
func ResponseAPIError(c echo.Context, status int, message string, redirect bool) error {
|
||||
returnValue := resultWrapper{
|
||||
Error: true,
|
||||
Message: message,
|
||||
Redirect: redirect,
|
||||
}
|
||||
|
||||
return c.JSON(status, returnValue)
|
||||
}
|
||||
|
||||
// ResponseAPIAuthError returns a standard API auth error to the response
|
||||
func ResponseAPIAuthError(c echo.Context, message string, redirect bool) error {
|
||||
return ResponseAPIError(c, http.StatusUnauthorized, message, redirect)
|
||||
}
|
||||
|
||||
// ResponseAPIServiceError returns a standard API service unavailable error to the response
|
||||
func ResponseAPIServiceError(c echo.Context, message string) error {
|
||||
return ResponseAPIError(c, http.StatusServiceUnavailable, message, false)
|
||||
}
|
||||
|
||||
// ResponseAPIValidationError returns a standard API validation error to the response
|
||||
func ResponseAPIValidationError(c echo.Context, message string) error {
|
||||
return ResponseAPIError(c, http.StatusUnprocessableEntity, message, false)
|
||||
}
|
||||
|
||||
// ResponseAPIFieldValidationError returns a standard API field validation error to the response
|
||||
func ResponseAPIFieldValidationError(c echo.Context, field string, message string) error {
|
||||
err := errors.NewValidationError(field, message)
|
||||
return HandleAPIError(c, err)
|
||||
}
|
||||
|
||||
// ResponseAPINotFoundError returns a standard API not found error to the response
|
||||
func ResponseAPINotFoundError(c echo.Context) error {
|
||||
return ResponseAPIError(c, http.StatusNotFound, "Not Found", false)
|
||||
}
|
||||
|
||||
func ignoreDefaultWrappedErrors(c echo.Context, errorToHandle *errors.WrappedError, handler func(echo.Context, error) error) error {
|
||||
err := errorToHandle.GetOriginalError()
|
||||
|
||||
if err != nil {
|
||||
switch e := (*err).(type) {
|
||||
case *errors.ValidationError:
|
||||
case *errors.NotAuthorizedError:
|
||||
case *errors.HTTPError:
|
||||
case awserr.Error:
|
||||
default:
|
||||
if e != sql.ErrNoRows {
|
||||
c.Logger().Errorf("%s", e.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return handler(c, *err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandleAPIError applies the default error handling to the response
|
||||
func HandleAPIError(c echo.Context, errorToHandle error) (err error) {
|
||||
statusCode := http.StatusServiceUnavailable
|
||||
errorMessage := "Service Unavailable"
|
||||
|
||||
if errorToHandle != nil {
|
||||
logger := c.Logger()
|
||||
errorString := errorToHandle.Error()
|
||||
|
||||
switch e := errorToHandle.(type) {
|
||||
case *errors.WrappedError:
|
||||
return ignoreDefaultWrappedErrors(c, e, HandleAPIError)
|
||||
|
||||
case *errors.ApplicationError:
|
||||
logger.Errorf("Application Error: %s - %v", e.Path, e.Message)
|
||||
|
||||
case *errors.ValidationError:
|
||||
return ResponseAPIValidationError(c, errorString)
|
||||
|
||||
case *errors.NotAuthorizedError:
|
||||
statusCode = http.StatusUnauthorized
|
||||
errorMessage = errorString
|
||||
|
||||
case *errors.HTTPError:
|
||||
statusCode = e.Status
|
||||
errorMessage = e.Message
|
||||
|
||||
case *mysql.MySQLError:
|
||||
logger.Errorf("MySQL Error: %v - %v", e.Number, e.Message)
|
||||
errorMessage = "Service temporarily unavailable"
|
||||
|
||||
case net.Error:
|
||||
logger.Errorf("Network/Connection error: %v", e.Error())
|
||||
errorMessage = "Service temporarily unavailable"
|
||||
|
||||
case *echo.HTTPError:
|
||||
statusCode = e.Code
|
||||
errorMessage = fmt.Sprint(e.Message)
|
||||
|
||||
case *exec.ExitError:
|
||||
logger.Errorf("Exec Error: %s - %v", e.ProcessState, e.Error())
|
||||
|
||||
default:
|
||||
if e == sql.ErrNoRows {
|
||||
logger.Debugf("SQL Error: %v", e.Error())
|
||||
return ResponseAPINotFoundError(c)
|
||||
} else if e == sql.ErrTxDone || strings.HasPrefix(errorString, "sql: ") {
|
||||
logger.Errorf("SQL Error: %v", e.Error())
|
||||
return ResponseAPIServiceError(c, "Service temporarily unavailable")
|
||||
}
|
||||
|
||||
logger.Errorf("%v: %v", reflect.TypeOf(e), e.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return ResponseAPIError(c, statusCode, errorMessage, false)
|
||||
}
|
||||
|
||||
// HandleHTMLError applies the default error handling to the response
|
||||
func HandleHTMLError(c echo.Context, errorToHandle error) error {
|
||||
statusCode := http.StatusServiceUnavailable
|
||||
errorMessage := "Service Unavailable"
|
||||
|
||||
if errorToHandle != nil {
|
||||
logger := c.Logger()
|
||||
errorString := errorToHandle.Error()
|
||||
|
||||
switch e := errorToHandle.(type) {
|
||||
case *errors.WrappedError:
|
||||
return ignoreDefaultWrappedErrors(c, e, HandleHTMLError)
|
||||
|
||||
case *errors.ApplicationError:
|
||||
logger.Errorf("Application Error: %s - %v", e.Path, e.Message)
|
||||
|
||||
case *errors.ValidationError:
|
||||
return ResponseAPIValidationError(c, errorString)
|
||||
|
||||
case *errors.NotAuthorizedError:
|
||||
return ResponseAPIError(c, http.StatusUnauthorized, errorString, false)
|
||||
|
||||
case *errors.HTTPError:
|
||||
errorMessage = e.Message
|
||||
|
||||
case *mysql.MySQLError:
|
||||
logger.Errorf("MySQL Error: %v - %v", e.Number, e.Message)
|
||||
errorMessage = "Service temporarily unavailable"
|
||||
|
||||
case net.Error:
|
||||
logger.Errorf("Network/Connection error: %v", e.Error())
|
||||
errorMessage = "Service temporarily unavailable"
|
||||
|
||||
case *echo.HTTPError:
|
||||
logger.Errorf("%v: %v - %v", reflect.TypeOf(e), e.Code, e.Message)
|
||||
statusCode = e.Code
|
||||
|
||||
default:
|
||||
if e == sql.ErrNoRows {
|
||||
logger.Debugf("SQL Error: %v", e.Error())
|
||||
statusCode = http.StatusNotFound
|
||||
errorMessage = "Not Found"
|
||||
} else if e == sql.ErrTxDone || strings.HasPrefix(errorString, "sql: ") {
|
||||
logger.Errorf("SQL Error: %v", e.Error())
|
||||
errorMessage = "Service temporarily unavailable"
|
||||
} else {
|
||||
logger.Errorf("%v: %v", reflect.TypeOf(e), e.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return c.HTML(statusCode, errorMessage)
|
||||
}
|
||||
Reference in New Issue
Block a user