mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
HTTP: Add function for using new style errors with fallback (#51627)
This commit is contained in:
parent
4ff0f006dd
commit
dd6d71ee4b
@ -239,6 +239,22 @@ func Err(err error) *NormalResponse {
|
||||
return resp
|
||||
}
|
||||
|
||||
// ErrOrFallback uses the information in an errutil.Error if available
|
||||
// and otherwise falls back to the status and message provided as
|
||||
// arguments.
|
||||
//
|
||||
// The signature is equivalent to that of Error which allows us to
|
||||
// rename this to Error when we're confident that that would be safe to
|
||||
// do.
|
||||
func ErrOrFallback(status int, message string, err error) *NormalResponse {
|
||||
grafanaErr := &errutil.Error{}
|
||||
if errors.As(err, grafanaErr) {
|
||||
return Err(err)
|
||||
}
|
||||
|
||||
return Error(status, message, err)
|
||||
}
|
||||
|
||||
// Empty creates an empty NormalResponse.
|
||||
func Empty(status int) *NormalResponse {
|
||||
return Respond(status, nil)
|
||||
|
127
pkg/api/response/response_test.go
Normal file
127
pkg/api/response/response_test.go
Normal file
@ -0,0 +1,127 @@
|
||||
package response
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/util/errutil"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestErrors(t *testing.T) {
|
||||
const fakeNotFoundMessage = "I looked, but did not find the thing"
|
||||
const genericErrorMessage = "Something went wrong in parsing the request"
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
|
||||
// inputs
|
||||
err error
|
||||
statusCode int
|
||||
message string
|
||||
|
||||
// responses
|
||||
legacyResponse *NormalResponse
|
||||
newResponse *NormalResponse
|
||||
fallbackUseNew bool
|
||||
compareErr bool
|
||||
}{
|
||||
{
|
||||
name: "base case",
|
||||
|
||||
legacyResponse: &NormalResponse{},
|
||||
newResponse: &NormalResponse{
|
||||
status: http.StatusInternalServerError,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "not found error",
|
||||
|
||||
err: errors.New("not found"),
|
||||
statusCode: http.StatusNotFound,
|
||||
message: fakeNotFoundMessage,
|
||||
|
||||
legacyResponse: &NormalResponse{
|
||||
status: http.StatusNotFound,
|
||||
errMessage: fakeNotFoundMessage,
|
||||
},
|
||||
newResponse: &NormalResponse{
|
||||
status: http.StatusInternalServerError,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "grafana error with fallback to other error",
|
||||
|
||||
err: errutil.NewBase(errutil.StatusTimeout, "thing.timeout").Errorf("whoops"),
|
||||
statusCode: http.StatusBadRequest,
|
||||
message: genericErrorMessage,
|
||||
|
||||
legacyResponse: &NormalResponse{
|
||||
status: http.StatusBadRequest,
|
||||
errMessage: genericErrorMessage,
|
||||
},
|
||||
newResponse: &NormalResponse{
|
||||
status: http.StatusGatewayTimeout,
|
||||
errMessage: errutil.StatusTimeout.String(),
|
||||
},
|
||||
fallbackUseNew: true,
|
||||
},
|
||||
}
|
||||
|
||||
compareResponses := func(expected *NormalResponse, actual *NormalResponse, compareErr bool) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
if expected == nil {
|
||||
require.Nil(t, actual)
|
||||
return
|
||||
}
|
||||
|
||||
require.NotNil(t, actual)
|
||||
assert.Equal(t, expected.status, actual.status)
|
||||
if expected.body != nil {
|
||||
assert.Equal(t, expected.body.Bytes(), actual.body.Bytes())
|
||||
}
|
||||
if expected.header != nil {
|
||||
assert.EqualValues(t, expected.header, actual.header)
|
||||
}
|
||||
assert.Equal(t, expected.errMessage, actual.errMessage)
|
||||
if compareErr {
|
||||
assert.ErrorIs(t, expected.err, actual.err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(
|
||||
tc.name+" Error",
|
||||
compareResponses(tc.legacyResponse, Error(
|
||||
tc.statusCode,
|
||||
tc.message,
|
||||
tc.err,
|
||||
), tc.compareErr),
|
||||
)
|
||||
|
||||
t.Run(
|
||||
tc.name+" Err",
|
||||
compareResponses(tc.newResponse, Err(
|
||||
tc.err,
|
||||
), tc.compareErr),
|
||||
)
|
||||
|
||||
fallbackResponse := tc.legacyResponse
|
||||
if tc.fallbackUseNew {
|
||||
fallbackResponse = tc.newResponse
|
||||
}
|
||||
t.Run(
|
||||
tc.name+" ErrOrFallback",
|
||||
compareResponses(fallbackResponse, ErrOrFallback(
|
||||
tc.statusCode,
|
||||
tc.message,
|
||||
tc.err,
|
||||
), tc.compareErr),
|
||||
)
|
||||
}
|
||||
}
|
@ -110,6 +110,10 @@ func (s CoreStatus) LogLevel() LogLevel {
|
||||
}
|
||||
}
|
||||
|
||||
func (s CoreStatus) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// ProxyStatus implies that an error originated from the data source
|
||||
// proxy.
|
||||
type ProxyStatus CoreStatus
|
||||
|
Loading…
Reference in New Issue
Block a user