// 2020 Rackspace, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"): you may // not use this file except in compliance with the License. You may obtain // a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations // under the License. package raxmiddleware import ( "fmt" "net/http" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" ) // RaxError is used to defined the specific type set in the gin.Errors implementation const RaxError gin.ErrorType = iota // Error is a custom error type for the authentication middleware. This allows you to // test if an error returned in the gin context came from the authentication middleware. type Error struct { StatusCode int Text string } // Error method is used to complete the implementation of the errors interface so // we can represent this as a custom error. func (e *Error) Error() string { return fmt.Sprintf("%d - %s", e.StatusCode, e.Text) } // AddError is a helper function to add this custom error to the gin.Context and set the type. func AddError(c *gin.Context, status int, err string) { e := &Error{StatusCode: status, Text: fmt.Sprintf("init error at %s:%s", c.HandlerName(), err)} logrus.Errorf("ERROR at: raxmiddleware.error:%s", e.Error()) _ = c.Error(e).SetType(RaxError) } // AbortOnErrorJSON is a helper middleware that will check for errors that have been // attached to the gin.Context during middleware processing. If there is an error, we exit // with a standard JSON response {"error": message} func AbortOnErrorJSON() gin.HandlerFunc { return func(c *gin.Context) { raxErrors := make([]string, 0) // Range through the list of errors in the gin.Context (if any), // and test each error to determine how we want to handle it. for _, e := range c.Errors { // Handle auth errors from the middleware if val, ok := e.Err.(*Error); ok { // nolint:staticcheck,ineffassign raxErrors = append(raxErrors, val.Error()) return } } if len(raxErrors) != 0 { c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": raxErrors}) } } }