mirror of https://github.com/grafana/grafana
prometheus: respect the http-method data source setting (#42753)
* prometheus: respect the http-method data source setting * removed forgotten if-true section * refactored json-checkpull/43344/head
parent
b867ecb515
commit
1879a6855e
@ -0,0 +1,29 @@ |
||||
package prometheus |
||||
|
||||
import ( |
||||
"net/http" |
||||
|
||||
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" |
||||
"github.com/grafana/grafana/pkg/infra/log" |
||||
) |
||||
|
||||
func forceHttpGetMiddleware(logger log.Logger) sdkhttpclient.Middleware { |
||||
return sdkhttpclient.NamedMiddlewareFunc("force-http-get", func(opts sdkhttpclient.Options, next http.RoundTripper) http.RoundTripper { |
||||
// the prometheus library we use does not allow us to set the http method.
|
||||
// it's behavior is to first try POST, and if it fails in certain ways
|
||||
// (for example, by returning a method-not-allowed error), it will try GET.
|
||||
// so here, we check if the http-method is POST, and if it is, we
|
||||
// return an artificial method-not-allowed response.
|
||||
// this will cause the prometheus library to retry with GET.
|
||||
return sdkhttpclient.RoundTripperFunc(func(req *http.Request) (*http.Response, error) { |
||||
if req.Method == http.MethodPost { |
||||
resp := &http.Response{ |
||||
StatusCode: http.StatusMethodNotAllowed, |
||||
} |
||||
return resp, nil |
||||
} |
||||
|
||||
return next.RoundTrip(req) |
||||
}) |
||||
}) |
||||
} |
@ -0,0 +1,84 @@ |
||||
package prometheus |
||||
|
||||
import ( |
||||
"net/http" |
||||
"testing" |
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" |
||||
"github.com/grafana/grafana/pkg/infra/log" |
||||
"github.com/stretchr/testify/require" |
||||
) |
||||
|
||||
func TestForceGet(t *testing.T) { |
||||
t.Run("With nil jsonOpts, should not force get-method", func(t *testing.T) { |
||||
var jsonOpts map[string]interface{} |
||||
require.False(t, forceHttpGet(jsonOpts)) |
||||
}) |
||||
|
||||
t.Run("With empty jsonOpts, should not force get-method", func(t *testing.T) { |
||||
jsonOpts := make(map[string]interface{}) |
||||
require.False(t, forceHttpGet(jsonOpts)) |
||||
}) |
||||
|
||||
t.Run("With httpMethod=nil, should not not force get-method", func(t *testing.T) { |
||||
jsonOpts := map[string]interface{}{ |
||||
"httpMethod": nil, |
||||
} |
||||
require.False(t, forceHttpGet(jsonOpts)) |
||||
}) |
||||
|
||||
t.Run("With httpMethod=post, should not force get-method", func(t *testing.T) { |
||||
jsonOpts := map[string]interface{}{ |
||||
"httpMethod": "POST", |
||||
} |
||||
require.False(t, forceHttpGet(jsonOpts)) |
||||
}) |
||||
|
||||
t.Run("With httpMethod=get, should force get-method", func(t *testing.T) { |
||||
jsonOpts := map[string]interface{}{ |
||||
"httpMethod": "get", |
||||
} |
||||
require.True(t, forceHttpGet(jsonOpts)) |
||||
}) |
||||
|
||||
t.Run("With httpMethod=GET, should force get-method", func(t *testing.T) { |
||||
jsonOpts := map[string]interface{}{ |
||||
"httpMethod": "GET", |
||||
} |
||||
require.True(t, forceHttpGet(jsonOpts)) |
||||
}) |
||||
} |
||||
|
||||
func TestEnsureHttpMethodMiddleware(t *testing.T) { |
||||
t.Run("Name should be correct", func(t *testing.T) { |
||||
finalRoundTripper := httpclient.RoundTripperFunc(func(req *http.Request) (*http.Response, error) { |
||||
return &http.Response{StatusCode: http.StatusOK}, nil |
||||
}) |
||||
mw := forceHttpGetMiddleware(log.New("test")) |
||||
rt := mw.CreateMiddleware(httpclient.Options{}, finalRoundTripper) |
||||
require.NotNil(t, rt) |
||||
middlewareName, ok := mw.(httpclient.MiddlewareName) |
||||
require.True(t, ok) |
||||
require.Equal(t, "force-http-get", middlewareName.MiddlewareName()) |
||||
}) |
||||
|
||||
t.Run("Should force GET method", func(t *testing.T) { |
||||
finalRoundTripper := httpclient.RoundTripperFunc(func(req *http.Request) (*http.Response, error) { |
||||
return &http.Response{StatusCode: http.StatusOK}, nil |
||||
}) |
||||
|
||||
mw := forceHttpGetMiddleware(log.New("test")) |
||||
rt := mw.CreateMiddleware(httpclient.Options{}, finalRoundTripper) |
||||
require.NotNil(t, rt) |
||||
|
||||
req, err := http.NewRequest(http.MethodPost, "http://example.com", nil) |
||||
require.NoError(t, err) |
||||
res, err := rt.RoundTrip(req) |
||||
require.NoError(t, err) |
||||
require.NotNil(t, res) |
||||
require.Equal(t, res.StatusCode, http.StatusMethodNotAllowed) |
||||
if res.Body != nil { |
||||
require.NoError(t, res.Body.Close()) |
||||
} |
||||
}) |
||||
} |
Loading…
Reference in new issue