mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-11-03 20:17:59 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			112 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package logical
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"net/http"
 | 
						|
 | 
						|
	"github.com/hashicorp/errwrap"
 | 
						|
	multierror "github.com/hashicorp/go-multierror"
 | 
						|
	"github.com/hashicorp/vault/helper/consts"
 | 
						|
)
 | 
						|
 | 
						|
// RespondErrorCommon pulls most of the functionality from http's
 | 
						|
// respondErrorCommon and some of http's handleLogical and makes it available
 | 
						|
// to both the http package and elsewhere.
 | 
						|
func RespondErrorCommon(req *Request, resp *Response, err error) (int, error) {
 | 
						|
	if err == nil && (resp == nil || !resp.IsError()) {
 | 
						|
		switch {
 | 
						|
		case req.Operation == ReadOperation:
 | 
						|
			if resp == nil {
 | 
						|
				return http.StatusNotFound, nil
 | 
						|
			}
 | 
						|
 | 
						|
		// Basically: if we have empty "keys" or no keys at all, 404. This
 | 
						|
		// provides consistency with GET.
 | 
						|
		case req.Operation == ListOperation && resp.WrapInfo == nil:
 | 
						|
			if resp == nil || len(resp.Data) == 0 {
 | 
						|
				return http.StatusNotFound, nil
 | 
						|
			}
 | 
						|
			keysRaw, ok := resp.Data["keys"]
 | 
						|
			if !ok || keysRaw == nil {
 | 
						|
				return http.StatusNotFound, nil
 | 
						|
			}
 | 
						|
			keys, ok := keysRaw.([]string)
 | 
						|
			if !ok {
 | 
						|
				return http.StatusInternalServerError, nil
 | 
						|
			}
 | 
						|
			if len(keys) == 0 {
 | 
						|
				return http.StatusNotFound, nil
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		return 0, nil
 | 
						|
	}
 | 
						|
 | 
						|
	if errwrap.ContainsType(err, new(ReplicationCodedError)) {
 | 
						|
		var allErrors error
 | 
						|
		codedErr := errwrap.GetType(err, new(ReplicationCodedError)).(*ReplicationCodedError)
 | 
						|
		errwrap.Walk(err, func(inErr error) {
 | 
						|
			newErr, ok := inErr.(*ReplicationCodedError)
 | 
						|
			if !ok {
 | 
						|
				allErrors = multierror.Append(allErrors, newErr)
 | 
						|
			}
 | 
						|
		})
 | 
						|
		if allErrors != nil {
 | 
						|
			return codedErr.Code, multierror.Append(errors.New(fmt.Sprintf("errors from both primary and secondary; primary error was %v; secondary errors follow", codedErr.Msg)), allErrors)
 | 
						|
		}
 | 
						|
		return codedErr.Code, errors.New(codedErr.Msg)
 | 
						|
	}
 | 
						|
 | 
						|
	// Start out with internal server error since in most of these cases there
 | 
						|
	// won't be a response so this won't be overridden
 | 
						|
	statusCode := http.StatusInternalServerError
 | 
						|
	// If we actually have a response, start out with bad request
 | 
						|
	if resp != nil {
 | 
						|
		statusCode = http.StatusBadRequest
 | 
						|
	}
 | 
						|
 | 
						|
	// Now, check the error itself; if it has a specific logical error, set the
 | 
						|
	// appropriate code
 | 
						|
	if err != nil {
 | 
						|
		switch {
 | 
						|
		case errwrap.ContainsType(err, new(StatusBadRequest)):
 | 
						|
			statusCode = http.StatusBadRequest
 | 
						|
		case errwrap.Contains(err, ErrPermissionDenied.Error()):
 | 
						|
			statusCode = http.StatusForbidden
 | 
						|
		case errwrap.Contains(err, ErrUnsupportedOperation.Error()):
 | 
						|
			statusCode = http.StatusMethodNotAllowed
 | 
						|
		case errwrap.Contains(err, ErrUnsupportedPath.Error()):
 | 
						|
			statusCode = http.StatusNotFound
 | 
						|
		case errwrap.Contains(err, ErrInvalidRequest.Error()):
 | 
						|
			statusCode = http.StatusBadRequest
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if resp != nil && resp.IsError() {
 | 
						|
		err = fmt.Errorf("%s", resp.Data["error"].(string))
 | 
						|
	}
 | 
						|
 | 
						|
	return statusCode, err
 | 
						|
}
 | 
						|
 | 
						|
// AdjustErrorStatusCode adjusts the status that will be sent in error
 | 
						|
// conditions in a way that can be shared across http's respondError and other
 | 
						|
// locations.
 | 
						|
func AdjustErrorStatusCode(status *int, err error) {
 | 
						|
	// Adjust status code when sealed
 | 
						|
	if errwrap.Contains(err, consts.ErrSealed.Error()) {
 | 
						|
		*status = http.StatusServiceUnavailable
 | 
						|
	}
 | 
						|
 | 
						|
	// Adjust status code on
 | 
						|
	if errwrap.Contains(err, "http: request body too large") {
 | 
						|
		*status = http.StatusRequestEntityTooLarge
 | 
						|
	}
 | 
						|
 | 
						|
	// Allow HTTPCoded error passthrough to specify a code
 | 
						|
	if t, ok := err.(HTTPCodedError); ok {
 | 
						|
		*status = t.Code()
 | 
						|
	}
 | 
						|
}
 |