Plugins: Use handler middleware from the SDK (#93445)

updates sdk to v0.251.0
This commit is contained in:
Marcus Efraimsson
2024-09-30 16:33:15 +02:00
committed by GitHub
parent 54faa541c3
commit b7a7f2bd62
47 changed files with 524 additions and 1448 deletions
@@ -1,60 +0,0 @@
package clientmiddleware
import (
"context"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins"
)
var _ = plugins.Client(&baseMiddleware{})
// The base middleware simply passes the request down the chain
// This allows middleware to avoid implementing all the noop functions
type baseMiddleware struct {
next plugins.Client
}
func (m *baseMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
return m.next.QueryData(ctx, req)
}
func (m *baseMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
return m.next.CallResource(ctx, req, sender)
}
func (m *baseMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
return m.next.CheckHealth(ctx, req)
}
func (m *baseMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
return m.next.CollectMetrics(ctx, req)
}
func (m *baseMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
return m.next.SubscribeStream(ctx, req)
}
func (m *baseMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
return m.next.PublishStream(ctx, req)
}
func (m *baseMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
return m.next.RunStream(ctx, req, sender)
}
// ValidateAdmission implements backend.AdmissionHandler.
func (m *baseMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
return m.next.ValidateAdmission(ctx, req)
}
// MutateAdmission implements backend.AdmissionHandler.
func (m *baseMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
return m.next.MutateAdmission(ctx, req)
}
// ConvertObject implements backend.AdmissionHandler.
func (m *baseMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
return m.next.ConvertObjects(ctx, req)
}
@@ -10,7 +10,6 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/caching"
"github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/featuremgmt"
@@ -19,15 +18,15 @@ import (
// needed to mock the function for testing
var shouldCacheQuery = awsds.ShouldCacheQuery
// NewCachingMiddleware creates a new plugins.ClientMiddleware that will
// NewCachingMiddleware creates a new backend.HandlerMiddleware that will
// attempt to read and write query results to the cache
func NewCachingMiddleware(cachingService caching.CachingService) plugins.ClientMiddleware {
func NewCachingMiddleware(cachingService caching.CachingService) backend.HandlerMiddleware {
return NewCachingMiddlewareWithFeatureManager(cachingService, nil)
}
// NewCachingMiddlewareWithFeatureManager creates a new plugins.ClientMiddleware that will
// NewCachingMiddlewareWithFeatureManager creates a new backend.HandlerMiddleware that will
// attempt to read and write query results to the cache with a feature manager
func NewCachingMiddlewareWithFeatureManager(cachingService caching.CachingService, features featuremgmt.FeatureToggles) plugins.ClientMiddleware {
func NewCachingMiddlewareWithFeatureManager(cachingService caching.CachingService, features featuremgmt.FeatureToggles) backend.HandlerMiddleware {
log := log.New("caching_middleware")
if err := prometheus.Register(QueryCachingRequestHistogram); err != nil {
log.Error("Error registering prometheus collector 'QueryRequestHistogram'", "error", err)
@@ -35,20 +34,18 @@ func NewCachingMiddlewareWithFeatureManager(cachingService caching.CachingServic
if err := prometheus.Register(ResourceCachingRequestHistogram); err != nil {
log.Error("Error registering prometheus collector 'ResourceRequestHistogram'", "error", err)
}
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &CachingMiddleware{
baseMiddleware: baseMiddleware{
next: next,
},
caching: cachingService,
log: log,
features: features,
BaseHandler: backend.NewBaseHandler(next),
caching: cachingService,
log: log,
features: features,
}
})
}
type CachingMiddleware struct {
baseMiddleware
backend.BaseHandler
caching caching.CachingService
log log.Logger
@@ -60,12 +57,12 @@ type CachingMiddleware struct {
// If the cache service is implemented, we capture the request duration as a metric. The service is expected to write any response headers.
func (m *CachingMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
if req == nil {
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
reqCtx := contexthandler.FromContext(ctx)
if reqCtx == nil {
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
// time how long this request takes
@@ -92,7 +89,7 @@ func (m *CachingMiddleware) QueryData(ctx context.Context, req *backend.QueryDat
}
// Cache miss; do the actual queries
resp, err := m.next.QueryData(ctx, req)
resp, err := m.BaseHandler.QueryData(ctx, req)
// Update the query cache with the result for this metrics request
if err == nil && cr.UpdateCacheFn != nil {
@@ -125,12 +122,12 @@ func (m *CachingMiddleware) QueryData(ctx context.Context, req *backend.QueryDat
// If the cache service is implemented, we capture the request duration as a metric. The service is expected to write any response headers.
func (m *CachingMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
if req == nil {
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
reqCtx := contexthandler.FromContext(ctx)
if reqCtx == nil {
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
// time how long this request takes
@@ -157,7 +154,7 @@ func (m *CachingMiddleware) CallResource(ctx context.Context, req *backend.CallR
// Cache miss; do the actual request
// If there is no update cache func, just pass in the original sender
if cr.UpdateCacheFn == nil {
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
// Otherwise, intercept the responses in a wrapped sender so we can cache them first
cacheSender := backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error {
@@ -165,5 +162,5 @@ func (m *CachingMiddleware) CallResource(ctx context.Context, req *backend.CallR
return sender.Send(res)
})
return m.next.CallResource(ctx, req, cacheSender)
return m.BaseHandler.CallResource(ctx, req, cacheSender)
}
@@ -7,7 +7,7 @@ import (
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
"github.com/grafana/grafana/pkg/services/caching"
"github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/featuremgmt"
@@ -22,9 +22,9 @@ func TestCachingMiddleware(t *testing.T) {
require.NoError(t, err)
cs := caching.NewFakeOSSCachingService()
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{}),
clienttest.WithMiddlewares(NewCachingMiddleware(cs)),
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{}),
handlertest.WithMiddlewares(NewCachingMiddleware(cs)),
)
jsonDataMap := map[string]any{}
@@ -63,7 +63,7 @@ func TestCachingMiddleware(t *testing.T) {
cs.ReturnHit = true
cs.ReturnQueryResponse = dataResponse
resp, err := cdt.Decorator.QueryData(req.Context(), qdr)
resp, err := cdt.MiddlewareHandler.QueryData(req.Context(), qdr)
assert.NoError(t, err)
// Cache service is called once
cs.AssertCalls(t, "HandleQueryRequest", 1)
@@ -92,7 +92,7 @@ func TestCachingMiddleware(t *testing.T) {
cs.ReturnHit = false
cs.ReturnQueryResponse = dataResponse
resp, err := cdt.Decorator.QueryData(req.Context(), qdr)
resp, err := cdt.MiddlewareHandler.QueryData(req.Context(), qdr)
assert.NoError(t, err)
// Cache service is called once
cs.AssertCalls(t, "HandleQueryRequest", 1)
@@ -105,9 +105,9 @@ func TestCachingMiddleware(t *testing.T) {
})
t.Run("with async queries", func(t *testing.T) {
asyncCdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{}),
clienttest.WithMiddlewares(
asyncCdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{}),
handlertest.WithMiddlewares(
NewCachingMiddlewareWithFeatureManager(cs, featuremgmt.WithFeatures(featuremgmt.FlagAwsAsyncQueryCaching))),
)
t.Run("If shoudCacheQuery returns true update cache function is called", func(t *testing.T) {
@@ -128,7 +128,7 @@ func TestCachingMiddleware(t *testing.T) {
cs.ReturnHit = false
cs.ReturnQueryResponse = dataResponse
resp, err := asyncCdt.Decorator.QueryData(req.Context(), qdr)
resp, err := asyncCdt.MiddlewareHandler.QueryData(req.Context(), qdr)
assert.NoError(t, err)
// Cache service is called once
cs.AssertCalls(t, "HandleQueryRequest", 1)
@@ -158,7 +158,7 @@ func TestCachingMiddleware(t *testing.T) {
cs.ReturnHit = false
cs.ReturnQueryResponse = dataResponse
resp, err := asyncCdt.Decorator.QueryData(req.Context(), qdr)
resp, err := asyncCdt.MiddlewareHandler.QueryData(req.Context(), qdr)
assert.NoError(t, err)
// Cache service is called once
cs.AssertCalls(t, "HandleQueryRequest", 1)
@@ -196,10 +196,10 @@ func TestCachingMiddleware(t *testing.T) {
}
cs := caching.NewFakeOSSCachingService()
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{}),
clienttest.WithMiddlewares(NewCachingMiddleware(cs)),
clienttest.WithResourceResponses([]*backend.CallResourceResponse{simulatedPluginResponse}),
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{}),
handlertest.WithMiddlewares(NewCachingMiddleware(cs)),
handlertest.WithResourceResponses([]*backend.CallResourceResponse{simulatedPluginResponse}),
)
jsonDataMap := map[string]any{}
@@ -235,7 +235,7 @@ func TestCachingMiddleware(t *testing.T) {
cs.ReturnHit = true
cs.ReturnResourceResponse = dataResponse
err := cdt.Decorator.CallResource(req.Context(), crr, storeOneResponseCallResourceSender)
err := cdt.MiddlewareHandler.CallResource(req.Context(), crr, storeOneResponseCallResourceSender)
assert.NoError(t, err)
// Cache service is called once
cs.AssertCalls(t, "HandleResourceRequest", 1)
@@ -255,7 +255,7 @@ func TestCachingMiddleware(t *testing.T) {
cs.ReturnHit = false
cs.ReturnResourceResponse = dataResponse
err := cdt.Decorator.CallResource(req.Context(), crr, storeOneResponseCallResourceSender)
err := cdt.MiddlewareHandler.CallResource(req.Context(), crr, storeOneResponseCallResourceSender)
assert.NoError(t, err)
// Cache service is called once
cs.AssertCalls(t, "HandleResourceRequest", 1)
@@ -272,9 +272,9 @@ func TestCachingMiddleware(t *testing.T) {
require.NoError(t, err)
cs := caching.NewFakeOSSCachingService()
cdt := clienttest.NewClientDecoratorTest(t,
cdt := handlertest.NewHandlerMiddlewareTest(t,
// Skip the request context in this case
clienttest.WithMiddlewares(NewCachingMiddleware(cs)),
handlertest.WithMiddlewares(NewCachingMiddleware(cs)),
)
reqCtx := contexthandler.FromContext(req.Context())
require.Nil(t, reqCtx)
@@ -298,7 +298,7 @@ func TestCachingMiddleware(t *testing.T) {
PluginContext: pluginCtx,
}
resp, err := cdt.Decorator.QueryData(context.Background(), qdr)
resp, err := cdt.MiddlewareHandler.QueryData(context.Background(), qdr)
assert.NoError(t, err)
// Cache service is never called
cs.AssertCalls(t, "HandleQueryRequest", 0)
@@ -315,7 +315,7 @@ func TestCachingMiddleware(t *testing.T) {
PluginContext: pluginCtx,
}
err := cdt.Decorator.CallResource(req.Context(), crr, nopCallResourceSender)
err := cdt.MiddlewareHandler.CallResource(req.Context(), crr, nopCallResourceSender)
assert.NoError(t, err)
// Cache service is never called
cs.AssertCalls(t, "HandleResourceRequest", 0)
@@ -5,25 +5,22 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/contexthandler"
)
// NewClearAuthHeadersMiddleware creates a new plugins.ClientMiddleware
// NewClearAuthHeadersMiddleware creates a new backend.HandlerMiddleware
// that will clear any outgoing HTTP headers that was part of the incoming
// HTTP request and used when authenticating to Grafana.
func NewClearAuthHeadersMiddleware() plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
func NewClearAuthHeadersMiddleware() backend.HandlerMiddleware {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &ClearAuthHeadersMiddleware{
baseMiddleware: baseMiddleware{
next: next,
},
BaseHandler: backend.NewBaseHandler(next),
}
})
}
type ClearAuthHeadersMiddleware struct {
baseMiddleware
backend.BaseHandler
}
func (m *ClearAuthHeadersMiddleware) clearHeaders(ctx context.Context, h backend.ForwardHTTPHeaders) {
@@ -43,30 +40,30 @@ func (m *ClearAuthHeadersMiddleware) clearHeaders(ctx context.Context, h backend
func (m *ClearAuthHeadersMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
if req == nil {
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
m.clearHeaders(ctx, req)
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
func (m *ClearAuthHeadersMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
if req == nil {
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
m.clearHeaders(ctx, req)
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
func (m *ClearAuthHeadersMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
if req == nil {
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
m.clearHeaders(ctx, req)
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
@@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
"github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
@@ -23,9 +23,9 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
req.Header.Set(otherHeader, "test")
t.Run("And requests are for a datasource", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{}),
clienttest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{}),
handlertest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
)
pluginCtx := backend.PluginContext{
@@ -33,7 +33,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
}
t.Run("Should not attach delete headers middleware when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -43,7 +43,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
})
t.Run("Should not attach delete headers middleware when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{otherHeader: {"test"}},
}, nopCallResourceSender)
@@ -53,7 +53,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
})
t.Run("Should not attach delete headers middleware when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -64,9 +64,9 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
})
t.Run("And requests are for an app", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{}),
clienttest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{}),
handlertest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
)
pluginCtx := backend.PluginContext{
@@ -74,7 +74,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
}
t.Run("Should not attach delete headers middleware when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -84,7 +84,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
})
t.Run("Should not attach delete headers middleware when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{otherHeader: {"test"}},
}, nopCallResourceSender)
@@ -94,7 +94,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
})
t.Run("Should not attach delete headers middleware when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -110,9 +110,9 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
require.NoError(t, err)
t.Run("And requests are for a datasource", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{}),
clienttest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{}),
handlertest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
)
req := req.WithContext(contexthandler.WithAuthHTTPHeaders(req.Context(), setting.NewCfg()))
@@ -126,7 +126,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
}
t.Run("Should attach delete headers middleware when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -137,7 +137,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
})
t.Run("Should attach delete headers middleware when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{otherHeader: {"test"}},
}, nopCallResourceSender)
@@ -148,7 +148,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
})
t.Run("Should attach delete headers middleware when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -160,9 +160,9 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
})
t.Run("And requests are for an app", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{}),
clienttest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{}),
handlertest.WithMiddlewares(NewClearAuthHeadersMiddleware()),
)
req := req.WithContext(contexthandler.WithAuthHTTPHeaders(req.Context(), setting.NewCfg()))
@@ -176,7 +176,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
}
t.Run("Should attach delete headers middleware when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -187,7 +187,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
})
t.Run("Should attach delete headers middleware when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{otherHeader: {"test"}},
}, nopCallResourceSender)
@@ -198,7 +198,7 @@ func TestClearAuthHeadersMiddleware(t *testing.T) {
})
t.Run("Should attach delete headers middleware when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -6,21 +6,20 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
)
// NewContextualLoggerMiddleware creates a new plugins.ClientMiddleware that adds
// NewContextualLoggerMiddleware creates a new backend.HandlerMiddleware that adds
// a contextual logger to the request context.
func NewContextualLoggerMiddleware() plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
func NewContextualLoggerMiddleware() backend.HandlerMiddleware {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &ContextualLoggerMiddleware{
next: next,
BaseHandler: backend.NewBaseHandler(next),
}
})
}
type ContextualLoggerMiddleware struct {
next plugins.Client
backend.BaseHandler
}
// instrumentContext adds a contextual logger with plugin and request details to the given context.
@@ -45,53 +44,53 @@ func instrumentContext(ctx context.Context, pCtx backend.PluginContext) context.
func (m *ContextualLoggerMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
ctx = instrumentContext(ctx, req.PluginContext)
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
func (m *ContextualLoggerMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
ctx = instrumentContext(ctx, req.PluginContext)
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
func (m *ContextualLoggerMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
ctx = instrumentContext(ctx, req.PluginContext)
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
func (m *ContextualLoggerMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
ctx = instrumentContext(ctx, req.PluginContext)
return m.next.CollectMetrics(ctx, req)
return m.BaseHandler.CollectMetrics(ctx, req)
}
func (m *ContextualLoggerMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
ctx = instrumentContext(ctx, req.PluginContext)
return m.next.SubscribeStream(ctx, req)
return m.BaseHandler.SubscribeStream(ctx, req)
}
func (m *ContextualLoggerMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
ctx = instrumentContext(ctx, req.PluginContext)
return m.next.PublishStream(ctx, req)
return m.BaseHandler.PublishStream(ctx, req)
}
func (m *ContextualLoggerMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
ctx = instrumentContext(ctx, req.PluginContext)
return m.next.RunStream(ctx, req, sender)
return m.BaseHandler.RunStream(ctx, req, sender)
}
// ValidateAdmission implements backend.AdmissionHandler.
func (m *ContextualLoggerMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
ctx = instrumentContext(ctx, req.PluginContext)
return m.next.ValidateAdmission(ctx, req)
return m.BaseHandler.ValidateAdmission(ctx, req)
}
// MutateAdmission implements backend.AdmissionHandler.
func (m *ContextualLoggerMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
ctx = instrumentContext(ctx, req.PluginContext)
return m.next.MutateAdmission(ctx, req)
return m.BaseHandler.MutateAdmission(ctx, req)
}
// ConvertObject implements backend.AdmissionHandler.
func (m *ContextualLoggerMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
ctx = instrumentContext(ctx, req.PluginContext)
return m.next.ConvertObjects(ctx, req)
return m.BaseHandler.ConvertObjects(ctx, req)
}
@@ -6,7 +6,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/util/proxyutil"
@@ -14,22 +13,20 @@ import (
const cookieHeaderName = "Cookie"
// NewCookiesMiddleware creates a new plugins.ClientMiddleware that will
// forward incoming HTTP request Cookies to outgoing plugins.Client requests
// NewCookiesMiddleware creates a new backend.HandlerMiddleware that will
// forward incoming HTTP request Cookies to outgoing backend.Handler requests
// if the datasource has enabled forwarding of cookies (keepCookies).
func NewCookiesMiddleware(skipCookiesNames []string) plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
func NewCookiesMiddleware(skipCookiesNames []string) backend.HandlerMiddleware {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &CookiesMiddleware{
baseMiddleware: baseMiddleware{
next: next,
},
BaseHandler: backend.NewBaseHandler(next),
skipCookiesNames: skipCookiesNames,
}
})
}
type CookiesMiddleware struct {
baseMiddleware
backend.BaseHandler
skipCookiesNames []string
}
@@ -87,7 +84,7 @@ func (m *CookiesMiddleware) applyCookies(ctx context.Context, pCtx backend.Plugi
func (m *CookiesMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
if req == nil {
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
err := m.applyCookies(ctx, req.PluginContext, req)
@@ -95,12 +92,12 @@ func (m *CookiesMiddleware) QueryData(ctx context.Context, req *backend.QueryDat
return nil, err
}
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
func (m *CookiesMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
if req == nil {
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
err := m.applyCookies(ctx, req.PluginContext, req)
@@ -108,12 +105,12 @@ func (m *CookiesMiddleware) CallResource(ctx context.Context, req *backend.CallR
return err
}
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
func (m *CookiesMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
if req == nil {
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
err := m.applyCookies(ctx, req.PluginContext, req)
@@ -121,5 +118,5 @@ func (m *CookiesMiddleware) CheckHealth(ctx context.Context, req *backend.CheckH
return nil, err
}
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
@@ -6,7 +6,7 @@ import (
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/require"
)
@@ -28,9 +28,9 @@ func TestCookiesMiddleware(t *testing.T) {
})
req.Header.Set(otherHeader, "test")
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{}),
clienttest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})),
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{}),
handlertest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})),
)
jsonDataMap := map[string]any{}
@@ -44,7 +44,7 @@ func TestCookiesMiddleware(t *testing.T) {
}
t.Run("Should not forward cookies when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -60,7 +60,7 @@ func TestCookiesMiddleware(t *testing.T) {
Headers: map[string][]string{otherHeader: {"test"}},
}
pReq.Headers[backend.CookiesHeaderName] = []string{req.Header.Get(backend.CookiesHeaderName)}
err = cdt.Decorator.CallResource(req.Context(), pReq, nopCallResourceSender)
err = cdt.MiddlewareHandler.CallResource(req.Context(), pReq, nopCallResourceSender)
require.NoError(t, err)
require.NotNil(t, cdt.CallResourceReq)
require.Len(t, cdt.CallResourceReq.Headers, 1)
@@ -68,7 +68,7 @@ func TestCookiesMiddleware(t *testing.T) {
})
t.Run("Should not forward cookies when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -97,9 +97,9 @@ func TestCookiesMiddleware(t *testing.T) {
req.Header.Set(otherHeader, "test")
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{}),
clienttest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})),
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{}),
handlertest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})),
)
jsonDataMap := map[string]any{
@@ -115,7 +115,7 @@ func TestCookiesMiddleware(t *testing.T) {
}
t.Run("Should forward cookies when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -127,7 +127,7 @@ func TestCookiesMiddleware(t *testing.T) {
})
t.Run("Should forward cookies when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{otherHeader: {"test"}},
}, nopCallResourceSender)
@@ -140,7 +140,7 @@ func TestCookiesMiddleware(t *testing.T) {
})
t.Run("Should forward cookies when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -166,9 +166,9 @@ func TestCookiesMiddleware(t *testing.T) {
})
req.Header.Set(otherHeader, "test")
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{}),
clienttest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})),
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{}),
handlertest.WithMiddlewares(NewCookiesMiddleware([]string{"grafana_session"})),
)
pluginCtx := backend.PluginContext{
@@ -181,7 +181,7 @@ func TestCookiesMiddleware(t *testing.T) {
Headers: map[string]string{otherHeader: "test"},
}
pReq.Headers[backend.CookiesHeaderName] = req.Header.Get(backend.CookiesHeaderName)
_, err = cdt.Decorator.QueryData(req.Context(), pReq)
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), pReq)
require.NoError(t, err)
require.NotNil(t, cdt.QueryDataReq)
require.Len(t, cdt.QueryDataReq.Headers, 1)
@@ -194,7 +194,7 @@ func TestCookiesMiddleware(t *testing.T) {
Headers: map[string][]string{otherHeader: {"test"}},
}
pReq.Headers[backend.CookiesHeaderName] = []string{req.Header.Get(backend.CookiesHeaderName)}
err = cdt.Decorator.CallResource(req.Context(), pReq, nopCallResourceSender)
err = cdt.MiddlewareHandler.CallResource(req.Context(), pReq, nopCallResourceSender)
require.NoError(t, err)
require.NotNil(t, cdt.CallResourceReq)
require.Len(t, cdt.CallResourceReq.Headers, 1)
@@ -207,7 +207,7 @@ func TestCookiesMiddleware(t *testing.T) {
Headers: map[string]string{otherHeader: "test"},
}
pReq.Headers[backend.CookiesHeaderName] = req.Header.Get(backend.CookiesHeaderName)
_, err = cdt.Decorator.CheckHealth(req.Context(), pReq)
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), pReq)
require.NoError(t, err)
require.NotNil(t, cdt.CheckHealthReq)
require.Len(t, cdt.CheckHealthReq.Headers, 1)
@@ -5,26 +5,23 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/contexthandler"
)
const forwardIDHeaderName = "X-Grafana-Id"
// NewForwardIDMiddleware creates a new plugins.ClientMiddleware that will
// set grafana id header on outgoing plugins.Client requests
func NewForwardIDMiddleware() plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
// NewForwardIDMiddleware creates a new backend.HandlerMiddleware that will
// set grafana id header on outgoing backend.Handler requests
func NewForwardIDMiddleware() backend.HandlerMiddleware {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &ForwardIDMiddleware{
baseMiddleware: baseMiddleware{
next: next,
},
BaseHandler: backend.NewBaseHandler(next),
}
})
}
type ForwardIDMiddleware struct {
baseMiddleware
backend.BaseHandler
}
func (m *ForwardIDMiddleware) applyToken(ctx context.Context, pCtx backend.PluginContext, req backend.ForwardHTTPHeaders) error {
@@ -43,7 +40,7 @@ func (m *ForwardIDMiddleware) applyToken(ctx context.Context, pCtx backend.Plugi
func (m *ForwardIDMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
if req == nil {
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
err := m.applyToken(ctx, req.PluginContext, req)
@@ -51,12 +48,12 @@ func (m *ForwardIDMiddleware) QueryData(ctx context.Context, req *backend.QueryD
return nil, err
}
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
func (m *ForwardIDMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
if req == nil {
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
err := m.applyToken(ctx, req.PluginContext, req)
@@ -64,12 +61,12 @@ func (m *ForwardIDMiddleware) CallResource(ctx context.Context, req *backend.Cal
return err
}
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
func (m *ForwardIDMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
if req == nil {
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
err := m.applyToken(ctx, req.PluginContext, req)
@@ -77,5 +74,5 @@ func (m *ForwardIDMiddleware) CheckHealth(ctx context.Context, req *backend.Chec
return nil, err
}
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
@@ -6,9 +6,9 @@ import (
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/user"
@@ -21,14 +21,14 @@ func TestForwardIDMiddleware(t *testing.T) {
}
t.Run("Should set forwarded id header if present", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewForwardIDMiddleware()))
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewForwardIDMiddleware()))
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
Context: &web.Context{Req: &http.Request{}},
SignedInUser: &user.SignedInUser{IDToken: "some-token"},
})
err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{
err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{
PluginContext: pluginContext,
}, nopCallResourceSender)
require.NoError(t, err)
@@ -37,14 +37,14 @@ func TestForwardIDMiddleware(t *testing.T) {
})
t.Run("Should not set forwarded id header if not present", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewForwardIDMiddleware()))
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewForwardIDMiddleware()))
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
Context: &web.Context{Req: &http.Request{}},
SignedInUser: &user.SignedInUser{},
})
err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{
err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{
PluginContext: pluginContext,
}, nopCallResourceSender)
require.NoError(t, err)
@@ -57,14 +57,14 @@ func TestForwardIDMiddleware(t *testing.T) {
}
t.Run("Should set forwarded id header to app plugin if present", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewForwardIDMiddleware()))
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewForwardIDMiddleware()))
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
Context: &web.Context{Req: &http.Request{}},
SignedInUser: &user.SignedInUser{IDToken: "some-token"},
})
err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{
err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{
PluginContext: pluginContext,
}, nopCallResourceSender)
require.NoError(t, err)
@@ -13,7 +13,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
@@ -24,24 +23,22 @@ const GrafanaSignedRequestID = "X-Grafana-Signed-Request-Id"
const XRealIPHeader = "X-Real-Ip"
const GrafanaInternalRequest = "X-Grafana-Internal-Request"
// NewHostedGrafanaACHeaderMiddleware creates a new plugins.ClientMiddleware that will
// NewHostedGrafanaACHeaderMiddleware creates a new backend.HandlerMiddleware that will
// generate a random request ID, sign it using internal key and populate X-Grafana-Request-ID with the request ID
// and X-Grafana-Signed-Request-ID with signed request ID. We can then use this to verify that the request
// is coming from hosted Grafana and is not an external request. This is used for IP range access control.
func NewHostedGrafanaACHeaderMiddleware(cfg *setting.Cfg) plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
func NewHostedGrafanaACHeaderMiddleware(cfg *setting.Cfg) backend.HandlerMiddleware {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &HostedGrafanaACHeaderMiddleware{
baseMiddleware: baseMiddleware{
next: next,
},
log: log.New("ip_header_middleware"),
cfg: cfg,
BaseHandler: backend.NewBaseHandler(next),
log: log.New("ip_header_middleware"),
cfg: cfg,
}
})
}
type HostedGrafanaACHeaderMiddleware struct {
baseMiddleware
backend.BaseHandler
log log.Logger
cfg *setting.Cfg
}
@@ -120,30 +117,30 @@ func GetGrafanaRequestIDHeaders(req *http.Request, cfg *setting.Cfg, logger log.
func (m *HostedGrafanaACHeaderMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
if req == nil {
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
m.applyGrafanaRequestIDHeader(ctx, req.PluginContext, req)
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
func (m *HostedGrafanaACHeaderMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
if req == nil {
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
m.applyGrafanaRequestIDHeader(ctx, req.PluginContext, req)
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
func (m *HostedGrafanaACHeaderMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
if req == nil {
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
m.applyGrafanaRequestIDHeader(ctx, req.PluginContext, req)
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
@@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/user"
@@ -26,7 +26,7 @@ func Test_HostedGrafanaACHeaderMiddleware(t *testing.T) {
allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"}
cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL}
cfg.IPRangeACSecretKey = "secret"
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
Context: &web.Context{Req: &http.Request{
@@ -35,7 +35,7 @@ func Test_HostedGrafanaACHeaderMiddleware(t *testing.T) {
SignedInUser: &user.SignedInUser{},
})
err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{
err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
URL: "https://logs.grafana.net",
@@ -68,14 +68,14 @@ func Test_HostedGrafanaACHeaderMiddleware(t *testing.T) {
allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"}
cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL}
cfg.IPRangeACSecretKey = "secret"
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
Context: &web.Context{Req: &http.Request{}},
SignedInUser: &user.SignedInUser{},
})
err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{
err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
URL: "https://logs.not-grafana.net",
@@ -93,14 +93,14 @@ func Test_HostedGrafanaACHeaderMiddleware(t *testing.T) {
allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"}
cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL}
cfg.IPRangeACSecretKey = "secret"
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
Context: &web.Context{Req: &http.Request{}},
SignedInUser: &user.SignedInUser{},
})
err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{
err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
URL: "https://logs.grafana.net/abc/../some/path",
@@ -118,14 +118,14 @@ func Test_HostedGrafanaACHeaderMiddleware(t *testing.T) {
allowedURL := &url.URL{Scheme: "https", Host: "logs.grafana.net"}
cfg.IPRangeACAllowedURLs = []*url.URL{allowedURL}
cfg.IPRangeACSecretKey = "secret"
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(NewHostedGrafanaACHeaderMiddleware(cfg)))
ctx := context.WithValue(context.Background(), ctxkey.Key{}, &contextmodel.ReqContext{
Context: &web.Context{Req: &http.Request{}},
SignedInUser: &user.SignedInUser{},
})
err := cdt.Decorator.CallResource(ctx, &backend.CallResourceRequest{
err := cdt.MiddlewareHandler.CallResource(ctx, &backend.CallResourceRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
URL: "https://logs.grafana.net",
@@ -7,26 +7,23 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
"github.com/grafana/grafana/pkg/plugins"
ngalertmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
)
const forwardPluginRequestHTTPHeaders = "forward-plugin-request-http-headers"
// NewHTTPClientMiddleware creates a new plugins.ClientMiddleware
// NewHTTPClientMiddleware creates a new backend.HandlerMiddleware
// that will forward plugin request headers as outgoing HTTP headers.
func NewHTTPClientMiddleware() plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
func NewHTTPClientMiddleware() backend.HandlerMiddleware {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &HTTPClientMiddleware{
baseMiddleware: baseMiddleware{
next: next,
},
BaseHandler: backend.NewBaseHandler(next),
}
})
}
type HTTPClientMiddleware struct {
baseMiddleware
backend.BaseHandler
}
func (m *HTTPClientMiddleware) applyHeaders(ctx context.Context, pReq any) context.Context {
@@ -69,30 +66,30 @@ func (m *HTTPClientMiddleware) applyHeaders(ctx context.Context, pReq any) conte
func (m *HTTPClientMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
if req == nil {
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
ctx = m.applyHeaders(ctx, req)
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
func (m *HTTPClientMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
if req == nil {
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
ctx = m.applyHeaders(ctx, req)
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
func (m *HTTPClientMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
if req == nil {
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
ctx = m.applyHeaders(ctx, req)
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
@@ -7,8 +7,8 @@ import (
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
ngalertmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/util/proxyutil"
@@ -23,9 +23,9 @@ func TestHTTPClientMiddleware(t *testing.T) {
require.NoError(t, err)
t.Run("And requests are for a datasource", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{}),
clienttest.WithMiddlewares(NewHTTPClientMiddleware()),
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{}),
handlertest.WithMiddlewares(NewHTTPClientMiddleware()),
)
pluginCtx := backend.PluginContext{
@@ -33,7 +33,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
}
t.Run("Should not forward headers when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "val"},
})
@@ -53,7 +53,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
})
t.Run("Should not forward headers when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{otherHeader: {"val"}},
}, nopCallResourceSender)
@@ -73,7 +73,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
})
t.Run("Should not forward headers when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "val"},
})
@@ -94,9 +94,9 @@ func TestHTTPClientMiddleware(t *testing.T) {
})
t.Run("And requests are for an app", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{}),
clienttest.WithMiddlewares(NewHTTPClientMiddleware()),
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{}),
handlertest.WithMiddlewares(NewHTTPClientMiddleware()),
)
pluginCtx := backend.PluginContext{
@@ -104,7 +104,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
}
t.Run("Should not forward headers when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -124,7 +124,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
})
t.Run("Should not forward headers when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{},
}, nopCallResourceSender)
@@ -144,7 +144,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
})
t.Run("Should not forward headers when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -184,9 +184,9 @@ func TestHTTPClientMiddleware(t *testing.T) {
}
t.Run("And requests are for a datasource", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{}),
clienttest.WithMiddlewares(NewHTTPClientMiddleware()),
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{}),
handlertest.WithMiddlewares(NewHTTPClientMiddleware()),
)
pluginCtx := backend.PluginContext{
@@ -194,7 +194,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
}
t.Run("Should forward headers when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: headers,
})
@@ -222,7 +222,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
})
t.Run("Should forward headers when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: crHeaders,
}, nopCallResourceSender)
@@ -250,7 +250,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
})
t.Run("Should forward headers when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: headers,
})
@@ -278,7 +278,7 @@ func TestHTTPClientMiddleware(t *testing.T) {
})
t.Run("Should not overwrite an existing header", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: headers,
})
@@ -7,21 +7,18 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/instrumentationutils"
plog "github.com/grafana/grafana/pkg/plugins/log"
"github.com/grafana/grafana/pkg/plugins/manager/registry"
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
)
// NewLoggerMiddleware creates a new plugins.ClientMiddleware that will
// NewLoggerMiddleware creates a new backend.HandlerMiddleware that will
// log requests.
func NewLoggerMiddleware(logger plog.Logger, pluginRegistry registry.Service) plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
func NewLoggerMiddleware(logger plog.Logger, pluginRegistry registry.Service) backend.HandlerMiddleware {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &LoggerMiddleware{
baseMiddleware: baseMiddleware{
next: next,
},
BaseHandler: backend.NewBaseHandler(next),
logger: logger,
pluginRegistry: pluginRegistry,
}
@@ -29,7 +26,7 @@ func NewLoggerMiddleware(logger plog.Logger, pluginRegistry registry.Service) pl
}
type LoggerMiddleware struct {
baseMiddleware
backend.BaseHandler
logger plog.Logger
pluginRegistry registry.Service
}
@@ -77,13 +74,13 @@ func (m *LoggerMiddleware) logRequest(ctx context.Context, pCtx backend.PluginCo
func (m *LoggerMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
if req == nil {
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
var resp *backend.QueryDataResponse
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.QueryData(ctx, req)
resp, innerErr = m.BaseHandler.QueryData(ctx, req)
if innerErr != nil {
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
@@ -110,11 +107,11 @@ func (m *LoggerMiddleware) QueryData(ctx context.Context, req *backend.QueryData
func (m *LoggerMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
if req == nil {
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
innerErr := m.next.CallResource(ctx, req, sender)
innerErr := m.BaseHandler.CallResource(ctx, req, sender)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
@@ -123,13 +120,13 @@ func (m *LoggerMiddleware) CallResource(ctx context.Context, req *backend.CallRe
func (m *LoggerMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
if req == nil {
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
var resp *backend.CheckHealthResult
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.CheckHealth(ctx, req)
resp, innerErr = m.BaseHandler.CheckHealth(ctx, req)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
@@ -138,13 +135,13 @@ func (m *LoggerMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHe
func (m *LoggerMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
if req == nil {
return m.next.CollectMetrics(ctx, req)
return m.BaseHandler.CollectMetrics(ctx, req)
}
var resp *backend.CollectMetricsResult
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.CollectMetrics(ctx, req)
resp, innerErr = m.BaseHandler.CollectMetrics(ctx, req)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
@@ -153,13 +150,13 @@ func (m *LoggerMiddleware) CollectMetrics(ctx context.Context, req *backend.Coll
func (m *LoggerMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
if req == nil {
return m.next.SubscribeStream(ctx, req)
return m.BaseHandler.SubscribeStream(ctx, req)
}
var resp *backend.SubscribeStreamResponse
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.SubscribeStream(ctx, req)
resp, innerErr = m.BaseHandler.SubscribeStream(ctx, req)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
@@ -168,13 +165,13 @@ func (m *LoggerMiddleware) SubscribeStream(ctx context.Context, req *backend.Sub
func (m *LoggerMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
if req == nil {
return m.next.PublishStream(ctx, req)
return m.BaseHandler.PublishStream(ctx, req)
}
var resp *backend.PublishStreamResponse
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.PublishStream(ctx, req)
resp, innerErr = m.BaseHandler.PublishStream(ctx, req)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
@@ -183,11 +180,11 @@ func (m *LoggerMiddleware) PublishStream(ctx context.Context, req *backend.Publi
func (m *LoggerMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
if req == nil {
return m.next.RunStream(ctx, req, sender)
return m.BaseHandler.RunStream(ctx, req, sender)
}
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
innerErr := m.next.RunStream(ctx, req, sender)
innerErr := m.BaseHandler.RunStream(ctx, req, sender)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
@@ -196,13 +193,13 @@ func (m *LoggerMiddleware) RunStream(ctx context.Context, req *backend.RunStream
func (m *LoggerMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
if req == nil {
return m.next.ValidateAdmission(ctx, req)
return m.BaseHandler.ValidateAdmission(ctx, req)
}
var resp *backend.ValidationResponse
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.ValidateAdmission(ctx, req)
resp, innerErr = m.BaseHandler.ValidateAdmission(ctx, req)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
@@ -211,13 +208,13 @@ func (m *LoggerMiddleware) ValidateAdmission(ctx context.Context, req *backend.A
func (m *LoggerMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
if req == nil {
return m.next.MutateAdmission(ctx, req)
return m.BaseHandler.MutateAdmission(ctx, req)
}
var resp *backend.MutationResponse
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.MutateAdmission(ctx, req)
resp, innerErr = m.BaseHandler.MutateAdmission(ctx, req)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
@@ -226,13 +223,13 @@ func (m *LoggerMiddleware) MutateAdmission(ctx context.Context, req *backend.Adm
func (m *LoggerMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
if req == nil {
return m.next.ConvertObjects(ctx, req)
return m.BaseHandler.ConvertObjects(ctx, req)
}
var resp *backend.ConversionResponse
err := m.logRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.ConvertObjects(ctx, req)
resp, innerErr = m.BaseHandler.ConvertObjects(ctx, req)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
@@ -25,7 +25,7 @@ type pluginMetrics struct {
// MetricsMiddleware is a middleware that instruments plugin requests.
// It tracks requests count, duration and size as prometheus metrics.
type MetricsMiddleware struct {
baseMiddleware
backend.BaseHandler
pluginMetrics
pluginRegistry registry.Service
}
@@ -75,12 +75,10 @@ func newMetricsMiddleware(promRegisterer prometheus.Registerer, pluginRegistry r
}
// NewMetricsMiddleware returns a new MetricsMiddleware.
func NewMetricsMiddleware(promRegisterer prometheus.Registerer, pluginRegistry registry.Service) plugins.ClientMiddleware {
func NewMetricsMiddleware(promRegisterer prometheus.Registerer, pluginRegistry registry.Service) backend.HandlerMiddleware {
imw := newMetricsMiddleware(promRegisterer, pluginRegistry)
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
imw.baseMiddleware = baseMiddleware{
next: next,
}
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
imw.BaseHandler = backend.NewBaseHandler(next)
return imw
})
}
@@ -154,7 +152,7 @@ func (m *MetricsMiddleware) QueryData(ctx context.Context, req *backend.QueryDat
var resp *backend.QueryDataResponse
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.QueryData(ctx, req)
resp, innerErr = m.BaseHandler.QueryData(ctx, req)
return instrumentationutils.RequestStatusFromQueryDataResponse(resp, innerErr), innerErr
})
@@ -166,7 +164,7 @@ func (m *MetricsMiddleware) CallResource(ctx context.Context, req *backend.CallR
return err
}
return m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
innerErr := m.next.CallResource(ctx, req, sender)
innerErr := m.BaseHandler.CallResource(ctx, req, sender)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
}
@@ -175,7 +173,7 @@ func (m *MetricsMiddleware) CheckHealth(ctx context.Context, req *backend.CheckH
var resp *backend.CheckHealthResult
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.CheckHealth(ctx, req)
resp, innerErr = m.BaseHandler.CheckHealth(ctx, req)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
@@ -186,7 +184,7 @@ func (m *MetricsMiddleware) CollectMetrics(ctx context.Context, req *backend.Col
var resp *backend.CollectMetricsResult
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.CollectMetrics(ctx, req)
resp, innerErr = m.BaseHandler.CollectMetrics(ctx, req)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
return resp, err
@@ -196,7 +194,7 @@ func (m *MetricsMiddleware) SubscribeStream(ctx context.Context, req *backend.Su
var resp *backend.SubscribeStreamResponse
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.SubscribeStream(ctx, req)
resp, innerErr = m.BaseHandler.SubscribeStream(ctx, req)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
return resp, err
@@ -206,7 +204,7 @@ func (m *MetricsMiddleware) PublishStream(ctx context.Context, req *backend.Publ
var resp *backend.PublishStreamResponse
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.PublishStream(ctx, req)
resp, innerErr = m.BaseHandler.PublishStream(ctx, req)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
return resp, err
@@ -214,7 +212,7 @@ func (m *MetricsMiddleware) PublishStream(ctx context.Context, req *backend.Publ
func (m *MetricsMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
innerErr := m.next.RunStream(ctx, req, sender)
innerErr := m.BaseHandler.RunStream(ctx, req, sender)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
return err
@@ -224,7 +222,7 @@ func (m *MetricsMiddleware) ValidateAdmission(ctx context.Context, req *backend.
var resp *backend.ValidationResponse
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.ValidateAdmission(ctx, req)
resp, innerErr = m.BaseHandler.ValidateAdmission(ctx, req)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
@@ -235,7 +233,7 @@ func (m *MetricsMiddleware) MutateAdmission(ctx context.Context, req *backend.Ad
var resp *backend.MutationResponse
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.MutateAdmission(ctx, req)
resp, innerErr = m.BaseHandler.MutateAdmission(ctx, req)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
@@ -246,7 +244,7 @@ func (m *MetricsMiddleware) ConvertObjects(ctx context.Context, req *backend.Con
var resp *backend.ConversionResponse
err := m.instrumentPluginRequest(ctx, req.PluginContext, func(ctx context.Context) (instrumentationutils.RequestStatus, error) {
var innerErr error
resp, innerErr = m.next.ConvertObjects(ctx, req)
resp, innerErr = m.BaseHandler.ConvertObjects(ctx, req)
return instrumentationutils.RequestStatusFromError(innerErr), innerErr
})
@@ -7,6 +7,7 @@ import (
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil"
dto "github.com/prometheus/client_model/go"
@@ -15,7 +16,6 @@ import (
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin"
"github.com/grafana/grafana/pkg/plugins/instrumentationutils"
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
)
@@ -34,36 +34,36 @@ func TestInstrumentationMiddleware(t *testing.T) {
t.Run("should instrument requests", func(t *testing.T) {
for _, tc := range []struct {
expEndpoint backend.Endpoint
fn func(cdt *clienttest.ClientDecoratorTest) error
fn func(cdt *handlertest.HandlerMiddlewareTest) error
shouldInstrumentRequestSize bool
}{
{
expEndpoint: backend.EndpointCheckHealth,
fn: func(cdt *clienttest.ClientDecoratorTest) error {
_, err := cdt.Decorator.CheckHealth(context.Background(), &backend.CheckHealthRequest{PluginContext: pCtx})
fn: func(cdt *handlertest.HandlerMiddlewareTest) error {
_, err := cdt.MiddlewareHandler.CheckHealth(context.Background(), &backend.CheckHealthRequest{PluginContext: pCtx})
return err
},
shouldInstrumentRequestSize: false,
},
{
expEndpoint: backend.EndpointCallResource,
fn: func(cdt *clienttest.ClientDecoratorTest) error {
return cdt.Decorator.CallResource(context.Background(), &backend.CallResourceRequest{PluginContext: pCtx}, nopCallResourceSender)
fn: func(cdt *handlertest.HandlerMiddlewareTest) error {
return cdt.MiddlewareHandler.CallResource(context.Background(), &backend.CallResourceRequest{PluginContext: pCtx}, nopCallResourceSender)
},
shouldInstrumentRequestSize: true,
},
{
expEndpoint: backend.EndpointQueryData,
fn: func(cdt *clienttest.ClientDecoratorTest) error {
_, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx})
fn: func(cdt *handlertest.HandlerMiddlewareTest) error {
_, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx})
return err
},
shouldInstrumentRequestSize: true,
},
{
expEndpoint: backend.EndpointCollectMetrics,
fn: func(cdt *clienttest.ClientDecoratorTest) error {
_, err := cdt.Decorator.CollectMetrics(context.Background(), &backend.CollectMetricsRequest{PluginContext: pCtx})
fn: func(cdt *handlertest.HandlerMiddlewareTest) error {
_, err := cdt.MiddlewareHandler.CollectMetrics(context.Background(), &backend.CollectMetricsRequest{PluginContext: pCtx})
return err
},
shouldInstrumentRequestSize: false,
@@ -77,9 +77,9 @@ func TestInstrumentationMiddleware(t *testing.T) {
}))
mw := newMetricsMiddleware(promRegistry, pluginsRegistry)
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(
plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
mw.next = next
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(
backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
mw.BaseHandler = backend.NewBaseHandler(next)
return mw
}),
))
@@ -154,10 +154,10 @@ func TestInstrumentationMiddlewareStatusSource(t *testing.T) {
JSONData: plugins.JSONData{ID: pluginID, Backend: true},
}))
metricsMw := newMetricsMiddleware(promRegistry, pluginsRegistry)
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(
cdt := handlertest.NewHandlerMiddlewareTest(t, handlertest.WithMiddlewares(
NewPluginRequestMetaMiddleware(),
plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
metricsMw.next = next
backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
metricsMw.BaseHandler = backend.NewBaseHandler(next)
return metricsMw
}),
NewStatusSourceMiddleware(),
@@ -166,10 +166,10 @@ func TestInstrumentationMiddlewareStatusSource(t *testing.T) {
t.Run("Metrics", func(t *testing.T) {
metricsMw.pluginMetrics.pluginRequestCounter.Reset()
cdt.TestClient.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
cdt.TestHandler.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
return &backend.QueryDataResponse{Responses: map[string]backend.DataResponse{"A": downstreamErrorResponse}}, nil
}
_, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx})
_, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx})
require.NoError(t, err)
counter, err := metricsMw.pluginMetrics.pluginRequestCounter.GetMetricWith(newLabels(
queryDataErrorCounterLabels,
@@ -235,12 +235,12 @@ func TestInstrumentationMiddlewareStatusSource(t *testing.T) {
cdt.QueryDataCtx = nil
cdt.QueryDataReq = nil
})
cdt.TestClient.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
cdt.TestHandler.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
cdt.QueryDataCtx = ctx
cdt.QueryDataReq = req
return &backend.QueryDataResponse{Responses: tc.responses}, nil
}
_, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx})
_, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx})
require.NoError(t, err)
ctxStatusSource := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx)
require.Equal(t, tc.expStatusSource, ctxStatusSource)
@@ -7,28 +7,25 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/oauthtoken"
)
// NewOAuthTokenMiddleware creates a new plugins.ClientMiddleware that will
// set OAuth token headers on outgoing plugins.Client requests if the
// NewOAuthTokenMiddleware creates a new backend.HandlerMiddleware that will
// set OAuth token headers on outgoing backend.Handler requests if the
// datasource has enabled Forward OAuth Identity (oauthPassThru).
func NewOAuthTokenMiddleware(oAuthTokenService oauthtoken.OAuthTokenService) plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
func NewOAuthTokenMiddleware(oAuthTokenService oauthtoken.OAuthTokenService) backend.HandlerMiddleware {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &OAuthTokenMiddleware{
baseMiddleware: baseMiddleware{
next: next,
},
BaseHandler: backend.NewBaseHandler(next),
oAuthTokenService: oAuthTokenService,
}
})
}
type OAuthTokenMiddleware struct {
baseMiddleware
backend.BaseHandler
oAuthTokenService oauthtoken.OAuthTokenService
}
@@ -87,7 +84,7 @@ func (m *OAuthTokenMiddleware) applyToken(ctx context.Context, pCtx backend.Plug
func (m *OAuthTokenMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
if req == nil {
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
err := m.applyToken(ctx, req.PluginContext, req)
@@ -95,12 +92,12 @@ func (m *OAuthTokenMiddleware) QueryData(ctx context.Context, req *backend.Query
return nil, err
}
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
func (m *OAuthTokenMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
if req == nil {
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
err := m.applyToken(ctx, req.PluginContext, req)
@@ -108,12 +105,12 @@ func (m *OAuthTokenMiddleware) CallResource(ctx context.Context, req *backend.Ca
return err
}
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
func (m *OAuthTokenMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
if req == nil {
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
err := m.applyToken(ctx, req.PluginContext, req)
@@ -121,5 +118,5 @@ func (m *OAuthTokenMiddleware) CheckHealth(ctx context.Context, req *backend.Che
return nil, err
}
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
@@ -6,7 +6,7 @@ import (
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
"github.com/grafana/grafana/pkg/services/oauthtoken/oauthtokentest"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/require"
@@ -23,9 +23,9 @@ func TestOAuthTokenMiddleware(t *testing.T) {
req.Header.Set(otherHeader, "test")
oAuthTokenService := &oauthtokentest.Service{}
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{}),
clienttest.WithMiddlewares(NewOAuthTokenMiddleware(oAuthTokenService)),
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{}),
handlertest.WithMiddlewares(NewOAuthTokenMiddleware(oAuthTokenService)),
)
jsonDataMap := map[string]any{}
@@ -39,7 +39,7 @@ func TestOAuthTokenMiddleware(t *testing.T) {
}
t.Run("Should not forward OAuth Identity when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -50,7 +50,7 @@ func TestOAuthTokenMiddleware(t *testing.T) {
})
t.Run("Should not forward OAuth Identity when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{otherHeader: {"test"}},
}, nopCallResourceSender)
@@ -61,7 +61,7 @@ func TestOAuthTokenMiddleware(t *testing.T) {
})
t.Run("Should not forward OAuth Identity when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -86,9 +86,9 @@ func TestOAuthTokenMiddleware(t *testing.T) {
oAuthTokenService := &oauthtokentest.Service{
Token: token,
}
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{}),
clienttest.WithMiddlewares(NewOAuthTokenMiddleware(oAuthTokenService)),
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{}),
handlertest.WithMiddlewares(NewOAuthTokenMiddleware(oAuthTokenService)),
)
jsonDataMap := map[string]any{
@@ -104,7 +104,7 @@ func TestOAuthTokenMiddleware(t *testing.T) {
}
t.Run("Should forward OAuth Identity when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -117,7 +117,7 @@ func TestOAuthTokenMiddleware(t *testing.T) {
})
t.Run("Should forward OAuth Identity when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{otherHeader: {"test"}},
}, nopCallResourceSender)
@@ -132,7 +132,7 @@ func TestOAuthTokenMiddleware(t *testing.T) {
})
t.Run("Should forward OAuth Identity when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{otherHeader: "test"},
})
@@ -5,24 +5,23 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
)
// NewPluginRequestMetaMiddleware returns a new plugins.ClientMiddleware that sets up the default
// NewPluginRequestMetaMiddleware returns a new backend.HandlerMiddleware that sets up the default
// values for the plugin request meta in the context.Context. All middlewares that are executed
// after this one are be able to access plugin request meta via the pluginrequestmeta package.
func NewPluginRequestMetaMiddleware() plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
func NewPluginRequestMetaMiddleware() backend.HandlerMiddleware {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &PluginRequestMetaMiddleware{
next: next,
BaseHandler: backend.NewBaseHandler(next),
defaultStatusSource: pluginrequestmeta.DefaultStatusSource,
}
})
}
type PluginRequestMetaMiddleware struct {
next plugins.Client
backend.BaseHandler
defaultStatusSource pluginrequestmeta.StatusSource
}
@@ -35,53 +34,53 @@ func (m *PluginRequestMetaMiddleware) withDefaultPluginRequestMeta(ctx context.C
func (m *PluginRequestMetaMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
ctx = m.withDefaultPluginRequestMeta(ctx)
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
func (m *PluginRequestMetaMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
ctx = m.withDefaultPluginRequestMeta(ctx)
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
func (m *PluginRequestMetaMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
ctx = m.withDefaultPluginRequestMeta(ctx)
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
func (m *PluginRequestMetaMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
ctx = m.withDefaultPluginRequestMeta(ctx)
return m.next.CollectMetrics(ctx, req)
return m.BaseHandler.CollectMetrics(ctx, req)
}
func (m *PluginRequestMetaMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
ctx = m.withDefaultPluginRequestMeta(ctx)
return m.next.SubscribeStream(ctx, req)
return m.BaseHandler.SubscribeStream(ctx, req)
}
func (m *PluginRequestMetaMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
ctx = m.withDefaultPluginRequestMeta(ctx)
return m.next.PublishStream(ctx, req)
return m.BaseHandler.PublishStream(ctx, req)
}
func (m *PluginRequestMetaMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
ctx = m.withDefaultPluginRequestMeta(ctx)
return m.next.RunStream(ctx, req, sender)
return m.BaseHandler.RunStream(ctx, req, sender)
}
// ValidateAdmission implements backend.AdmissionHandler.
func (m *PluginRequestMetaMiddleware) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
ctx = m.withDefaultPluginRequestMeta(ctx)
return m.next.ValidateAdmission(ctx, req)
return m.BaseHandler.ValidateAdmission(ctx, req)
}
// MutateAdmission implements backend.AdmissionHandler.
func (m *PluginRequestMetaMiddleware) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
ctx = m.withDefaultPluginRequestMeta(ctx)
return m.next.MutateAdmission(ctx, req)
return m.BaseHandler.MutateAdmission(ctx, req)
}
// ConvertObject implements backend.AdmissionHandler.
func (m *PluginRequestMetaMiddleware) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
ctx = m.withDefaultPluginRequestMeta(ctx)
return m.next.ConvertObjects(ctx, req)
return m.BaseHandler.ConvertObjects(ctx, req)
}
@@ -5,34 +5,33 @@ import (
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
)
func TestPluginRequestMetaMiddleware(t *testing.T) {
t.Run("default", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithMiddlewares(NewPluginRequestMetaMiddleware()),
cdt := handlertest.NewHandlerMiddlewareTest(t,
handlertest.WithMiddlewares(NewPluginRequestMetaMiddleware()),
)
_, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{})
_, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{})
require.NoError(t, err)
ss := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx)
require.Equal(t, pluginrequestmeta.StatusSourcePlugin, ss)
})
t.Run("other value", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithMiddlewares(plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
cdt := handlertest.NewHandlerMiddlewareTest(t,
handlertest.WithMiddlewares(backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &PluginRequestMetaMiddleware{
next: next,
BaseHandler: backend.NewBaseHandler(next),
defaultStatusSource: "test",
}
})),
)
_, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{})
_, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{})
require.NoError(t, err)
ss := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx)
require.Equal(t, pluginrequestmeta.StatusSource("test"), ss)
@@ -1,52 +0,0 @@
package clientmiddleware
import (
"context"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/util/proxyutil"
)
// NewResourceResponseMiddleware creates a new plugins.ClientMiddleware
// that will enforce HTTP header rules for backend.CallResourceResponse's.
func NewResourceResponseMiddleware() plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
return &ResourceResponseMiddleware{
baseMiddleware: baseMiddleware{
next: next,
},
}
})
}
type ResourceResponseMiddleware struct {
baseMiddleware
}
func (m *ResourceResponseMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
return m.next.QueryData(ctx, req)
}
func (m *ResourceResponseMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
if req == nil || sender == nil {
return m.next.CallResource(ctx, req, sender)
}
processedStreams := 0
wrappedSender := backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error {
if processedStreams == 0 {
if res.Headers == nil {
res.Headers = map[string][]string{}
}
proxyutil.SetProxyResponseHeaders(res.Headers)
}
processedStreams++
return sender.Send(res)
})
return m.next.CallResource(ctx, req, wrappedSender)
}
@@ -1,41 +0,0 @@
package clientmiddleware
import (
"context"
"net/http"
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
"github.com/stretchr/testify/require"
)
func TestResourceResponseMiddleware(t *testing.T) {
t.Run("Should set proxy response headers when calling CallResource", func(t *testing.T) {
crResp := &backend.CallResourceResponse{
Status: http.StatusOK,
Headers: map[string][]string{
"X-Custom": {"Should not be deleted"},
},
}
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithMiddlewares(NewResourceResponseMiddleware()),
clienttest.WithResourceResponses([]*backend.CallResourceResponse{crResp}),
)
var sentResponse *backend.CallResourceResponse
sender := backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error {
sentResponse = res
return nil
})
err := cdt.Decorator.CallResource(context.Background(), &backend.CallResourceRequest{
PluginContext: backend.PluginContext{},
}, sender)
require.NoError(t, err)
require.NotNil(t, sentResponse)
require.Equal(t, "sandbox", sentResponse.Headers["Content-Security-Policy"][0])
require.Equal(t, "Should not be deleted", sentResponse.Headers["X-Custom"][0])
})
}
@@ -6,30 +6,27 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
)
// NewStatusSourceMiddleware returns a new plugins.ClientMiddleware that sets the status source in the
// NewStatusSourceMiddleware returns a new backend.HandlerMiddleware that sets the status source in the
// plugin request meta stored in the context.Context, according to the query data responses returned by QueryError.
// If at least one query data response has a "downstream" status source and there isn't one with a "plugin" status source,
// the plugin request meta in the context is set to "downstream".
func NewStatusSourceMiddleware() plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
func NewStatusSourceMiddleware() backend.HandlerMiddleware {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &StatusSourceMiddleware{
baseMiddleware: baseMiddleware{
next: next,
},
BaseHandler: backend.NewBaseHandler(next),
}
})
}
type StatusSourceMiddleware struct {
baseMiddleware
backend.BaseHandler
}
func (m *StatusSourceMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
resp, err := m.next.QueryData(ctx, req)
resp, err := m.BaseHandler.QueryData(ctx, req)
if resp == nil || len(resp.Responses) == 0 {
return resp, err
}
@@ -6,9 +6,9 @@ import (
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
"github.com/grafana/grafana/pkg/plugins/pluginrequestmeta"
)
@@ -68,18 +68,18 @@ func TestStatusSourceMiddleware(t *testing.T) {
},
} {
t.Run(tc.name, func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithMiddlewares(
cdt := handlertest.NewHandlerMiddlewareTest(t,
handlertest.WithMiddlewares(
NewPluginRequestMetaMiddleware(),
NewStatusSourceMiddleware(),
),
)
cdt.TestClient.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
cdt.TestHandler.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
cdt.QueryDataCtx = ctx
return tc.queryDataResponse, nil
}
_, _ = cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{})
_, _ = cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{})
ss := pluginrequestmeta.StatusSourceFromContext(cdt.QueryDataCtx)
require.Equal(t, tc.expStatusSource, ss)
@@ -1,6 +1,31 @@
package clientmiddleware
import "github.com/grafana/grafana-plugin-sdk-go/backend"
import (
"net/http"
"net/http/httptest"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/web"
)
func WithReqContext(req *http.Request, user *user.SignedInUser) handlertest.HandlerMiddlewareTestOption {
return handlertest.HandlerMiddlewareTestOption(func(cdt *handlertest.HandlerMiddlewareTest) {
reqContext := &contextmodel.ReqContext{
Context: &web.Context{
Req: req,
Resp: web.NewResponseWriter(req.Method, httptest.NewRecorder()),
},
SignedInUser: user,
}
ctx := ctxkey.Set(req.Context(), reqContext)
*req = *req.WithContext(ctx)
})
}
var nopCallResourceSender = backend.CallResourceResponseSenderFunc(func(res *backend.CallResourceResponse) error {
return nil
@@ -5,28 +5,25 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/query"
)
// NewTracingHeaderMiddleware creates a new plugins.ClientMiddleware that will
// populate useful tracing headers on outgoing plugins.Client and HTTP
// NewTracingHeaderMiddleware creates a new backend.HandlerMiddleware that will
// populate useful tracing headers on outgoing backend.Handler and HTTP
// requests.
// Tracing headers are X-Datasource-Uid, X-Dashboard-Uid,
// X-Panel-Id, X-Grafana-Org-Id.
func NewTracingHeaderMiddleware() plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
func NewTracingHeaderMiddleware() backend.HandlerMiddleware {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &TracingHeaderMiddleware{
baseMiddleware: baseMiddleware{
next: next,
},
BaseHandler: backend.NewBaseHandler(next),
}
})
}
type TracingHeaderMiddleware struct {
baseMiddleware
backend.BaseHandler
}
func (m *TracingHeaderMiddleware) applyHeaders(ctx context.Context, req backend.ForwardHTTPHeaders) {
@@ -49,22 +46,22 @@ func (m *TracingHeaderMiddleware) applyHeaders(ctx context.Context, req backend.
func (m *TracingHeaderMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
if req == nil {
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
m.applyHeaders(ctx, req)
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
func (m *TracingHeaderMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
func (m *TracingHeaderMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
if req == nil {
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
m.applyHeaders(ctx, req)
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
@@ -5,7 +5,7 @@ import (
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/require"
)
@@ -25,15 +25,15 @@ func TestTracingHeaderMiddleware(t *testing.T) {
}
t.Run("tracing headers are not set for query data", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{
IsAnonymous: true,
Login: "anonymous"},
),
clienttest.WithMiddlewares(NewTracingHeaderMiddleware()),
handlertest.WithMiddlewares(NewTracingHeaderMiddleware()),
)
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -43,15 +43,15 @@ func TestTracingHeaderMiddleware(t *testing.T) {
})
t.Run("tracing headers are not set for health check", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{
IsAnonymous: true,
Login: "anonymous"},
),
clienttest.WithMiddlewares(NewTracingHeaderMiddleware()),
handlertest.WithMiddlewares(NewTracingHeaderMiddleware()),
)
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -69,15 +69,15 @@ func TestTracingHeaderMiddleware(t *testing.T) {
}
t.Run("tracing headers are not set for query data", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{
IsAnonymous: true,
Login: "anonymous"},
),
clienttest.WithMiddlewares(NewTracingHeaderMiddleware()),
handlertest.WithMiddlewares(NewTracingHeaderMiddleware()),
)
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -87,15 +87,15 @@ func TestTracingHeaderMiddleware(t *testing.T) {
})
t.Run("tracing headers are not set for health check", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{
IsAnonymous: true,
Login: "anonymous"},
),
clienttest.WithMiddlewares(NewTracingHeaderMiddleware()),
handlertest.WithMiddlewares(NewTracingHeaderMiddleware()),
)
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -120,15 +120,15 @@ func TestTracingHeaderMiddleware(t *testing.T) {
}
t.Run("tracing headers are set for query data", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{
IsAnonymous: true,
Login: "anonymous"},
),
clienttest.WithMiddlewares(NewTracingHeaderMiddleware()),
handlertest.WithMiddlewares(NewTracingHeaderMiddleware()),
)
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -144,15 +144,15 @@ func TestTracingHeaderMiddleware(t *testing.T) {
})
t.Run("tracing headers are set for health check", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{
IsAnonymous: true,
Login: "anonymous"},
),
clienttest.WithMiddlewares(NewTracingHeaderMiddleware()),
handlertest.WithMiddlewares(NewTracingHeaderMiddleware()),
)
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -11,24 +11,23 @@ import (
"go.opentelemetry.io/otel/trace"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/query"
)
// NewTracingMiddleware returns a new middleware that creates a new span on every method call.
func NewTracingMiddleware(tracer tracing.Tracer) plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
func NewTracingMiddleware(tracer tracing.Tracer) backend.HandlerMiddleware {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &TracingMiddleware{
tracer: tracer,
next: next,
tracer: tracer,
BaseHandler: backend.NewBaseHandler(next),
}
})
}
type TracingMiddleware struct {
backend.BaseHandler
tracer tracing.Tracer
next plugins.Client
}
// setSpanAttributeFromHTTPHeader takes a ReqContext and a span, and adds the specified HTTP header as a span attribute
@@ -84,7 +83,7 @@ func (m *TracingMiddleware) QueryData(ctx context.Context, req *backend.QueryDat
var err error
ctx, end := m.traceWrap(ctx, req.PluginContext)
defer func() { end(err) }()
resp, err := m.next.QueryData(ctx, req)
resp, err := m.BaseHandler.QueryData(ctx, req)
return resp, err
}
@@ -92,7 +91,7 @@ func (m *TracingMiddleware) CallResource(ctx context.Context, req *backend.CallR
var err error
ctx, end := m.traceWrap(ctx, req.PluginContext)
defer func() { end(err) }()
err = m.next.CallResource(ctx, req, sender)
err = m.BaseHandler.CallResource(ctx, req, sender)
return err
}
@@ -100,7 +99,7 @@ func (m *TracingMiddleware) CheckHealth(ctx context.Context, req *backend.CheckH
var err error
ctx, end := m.traceWrap(ctx, req.PluginContext)
defer func() { end(err) }()
resp, err := m.next.CheckHealth(ctx, req)
resp, err := m.BaseHandler.CheckHealth(ctx, req)
return resp, err
}
@@ -108,7 +107,7 @@ func (m *TracingMiddleware) CollectMetrics(ctx context.Context, req *backend.Col
var err error
ctx, end := m.traceWrap(ctx, req.PluginContext)
defer func() { end(err) }()
resp, err := m.next.CollectMetrics(ctx, req)
resp, err := m.BaseHandler.CollectMetrics(ctx, req)
return resp, err
}
@@ -116,7 +115,7 @@ func (m *TracingMiddleware) SubscribeStream(ctx context.Context, req *backend.Su
var err error
ctx, end := m.traceWrap(ctx, req.PluginContext)
defer func() { end(err) }()
resp, err := m.next.SubscribeStream(ctx, req)
resp, err := m.BaseHandler.SubscribeStream(ctx, req)
return resp, err
}
@@ -124,7 +123,7 @@ func (m *TracingMiddleware) PublishStream(ctx context.Context, req *backend.Publ
var err error
ctx, end := m.traceWrap(ctx, req.PluginContext)
defer func() { end(err) }()
resp, err := m.next.PublishStream(ctx, req)
resp, err := m.BaseHandler.PublishStream(ctx, req)
return resp, err
}
@@ -132,7 +131,7 @@ func (m *TracingMiddleware) RunStream(ctx context.Context, req *backend.RunStrea
var err error
ctx, end := m.traceWrap(ctx, req.PluginContext)
defer func() { end(err) }()
err = m.next.RunStream(ctx, req, sender)
err = m.BaseHandler.RunStream(ctx, req, sender)
return err
}
@@ -141,7 +140,7 @@ func (m *TracingMiddleware) ValidateAdmission(ctx context.Context, req *backend.
var err error
ctx, end := m.traceWrap(ctx, req.PluginContext)
defer func() { end(err) }()
resp, err := m.next.ValidateAdmission(ctx, req)
resp, err := m.BaseHandler.ValidateAdmission(ctx, req)
return resp, err
}
@@ -150,7 +149,7 @@ func (m *TracingMiddleware) MutateAdmission(ctx context.Context, req *backend.Ad
var err error
ctx, end := m.traceWrap(ctx, req.PluginContext)
defer func() { end(err) }()
resp, err := m.next.MutateAdmission(ctx, req)
resp, err := m.BaseHandler.MutateAdmission(ctx, req)
return resp, err
}
@@ -159,6 +158,6 @@ func (m *TracingMiddleware) ConvertObjects(ctx context.Context, req *backend.Con
var err error
ctx, end := m.traceWrap(ctx, req.PluginContext)
defer func() { end(err) }()
resp, err := m.next.ConvertObjects(ctx, req)
resp, err := m.BaseHandler.ConvertObjects(ctx, req)
return resp, err
}
@@ -7,6 +7,7 @@ import (
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/attribute"
@@ -16,8 +17,6 @@ import (
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/web"
@@ -30,13 +29,13 @@ func TestTracingMiddleware(t *testing.T) {
for _, tc := range []struct {
name string
run func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error
run func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error
expSpanName string
}{
{
name: "QueryData",
run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error {
_, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{
run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error {
_, err := cdt.MiddlewareHandler.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
})
return err
@@ -45,8 +44,8 @@ func TestTracingMiddleware(t *testing.T) {
},
{
name: "CallResource",
run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error {
return cdt.Decorator.CallResource(context.Background(), &backend.CallResourceRequest{
run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error {
return cdt.MiddlewareHandler.CallResource(context.Background(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
}, nopCallResourceSender)
},
@@ -54,8 +53,8 @@ func TestTracingMiddleware(t *testing.T) {
},
{
name: "CheckHealth",
run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error {
_, err := cdt.Decorator.CheckHealth(context.Background(), &backend.CheckHealthRequest{
run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error {
_, err := cdt.MiddlewareHandler.CheckHealth(context.Background(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
})
return err
@@ -64,8 +63,8 @@ func TestTracingMiddleware(t *testing.T) {
},
{
name: "CollectMetrics",
run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error {
_, err := cdt.Decorator.CollectMetrics(context.Background(), &backend.CollectMetricsRequest{
run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error {
_, err := cdt.MiddlewareHandler.CollectMetrics(context.Background(), &backend.CollectMetricsRequest{
PluginContext: pluginCtx,
})
return err
@@ -74,8 +73,8 @@ func TestTracingMiddleware(t *testing.T) {
},
{
name: "SubscribeStream",
run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error {
_, err := cdt.Decorator.SubscribeStream(context.Background(), &backend.SubscribeStreamRequest{
run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error {
_, err := cdt.MiddlewareHandler.SubscribeStream(context.Background(), &backend.SubscribeStreamRequest{
PluginContext: pluginCtx,
})
return err
@@ -84,8 +83,8 @@ func TestTracingMiddleware(t *testing.T) {
},
{
name: "PublishStream",
run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error {
_, err := cdt.Decorator.PublishStream(context.Background(), &backend.PublishStreamRequest{
run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error {
_, err := cdt.MiddlewareHandler.PublishStream(context.Background(), &backend.PublishStreamRequest{
PluginContext: pluginCtx,
})
return err
@@ -94,8 +93,8 @@ func TestTracingMiddleware(t *testing.T) {
},
{
name: "RunStream",
run: func(pluginCtx backend.PluginContext, cdt *clienttest.ClientDecoratorTest) error {
return cdt.Decorator.RunStream(context.Background(), &backend.RunStreamRequest{
run: func(pluginCtx backend.PluginContext, cdt *handlertest.HandlerMiddlewareTest) error {
return cdt.MiddlewareHandler.RunStream(context.Background(), &backend.RunStreamRequest{
PluginContext: pluginCtx,
}, &backend.StreamSender{})
},
@@ -107,9 +106,9 @@ func TestTracingMiddleware(t *testing.T) {
spanRecorder := tracetest.NewSpanRecorder()
tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder))
cdt := clienttest.NewClientDecoratorTest(
cdt := handlertest.NewHandlerMiddlewareTest(
t,
clienttest.WithMiddlewares(NewTracingMiddleware(tracer)),
handlertest.WithMiddlewares(NewTracingMiddleware(tracer)),
)
err := tc.run(pluginCtx, cdt)
@@ -126,9 +125,9 @@ func TestTracingMiddleware(t *testing.T) {
spanRecorder := tracetest.NewSpanRecorder()
tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder))
cdt := clienttest.NewClientDecoratorTest(
cdt := handlertest.NewHandlerMiddlewareTest(
t,
clienttest.WithMiddlewares(
handlertest.WithMiddlewares(
NewTracingMiddleware(tracer),
newAlwaysErrorMiddleware(errors.New("ops")),
),
@@ -150,9 +149,9 @@ func TestTracingMiddleware(t *testing.T) {
spanRecorder := tracetest.NewSpanRecorder()
tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder))
cdt := clienttest.NewClientDecoratorTest(
cdt := handlertest.NewHandlerMiddlewareTest(
t,
clienttest.WithMiddlewares(
handlertest.WithMiddlewares(
NewTracingMiddleware(tracer),
newAlwaysPanicMiddleware("panic!"),
),
@@ -314,12 +313,12 @@ func TestTracingMiddlewareAttributes(t *testing.T) {
spanRecorder := tracetest.NewSpanRecorder()
tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder))
cdt := clienttest.NewClientDecoratorTest(
cdt := handlertest.NewHandlerMiddlewareTest(
t,
clienttest.WithMiddlewares(NewTracingMiddleware(tracer)),
handlertest.WithMiddlewares(NewTracingMiddleware(tracer)),
)
_, err := cdt.Decorator.QueryData(ctx, req)
_, err := cdt.MiddlewareHandler.QueryData(ctx, req)
require.NoError(t, err)
spans := spanRecorder.Ended()
require.Len(t, spans, 1, "must have 1 span")
@@ -403,8 +402,8 @@ func (m *alwaysErrorFuncMiddleware) ConvertObjects(ctx context.Context, req *bac
}
// newAlwaysErrorMiddleware returns a new middleware that always returns the specified error.
func newAlwaysErrorMiddleware(err error) plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
func newAlwaysErrorMiddleware(err error) backend.HandlerMiddleware {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &alwaysErrorFuncMiddleware{func() error {
return err
}}
@@ -412,8 +411,8 @@ func newAlwaysErrorMiddleware(err error) plugins.ClientMiddleware {
}
// newAlwaysPanicMiddleware returns a new middleware that always panics with the specified message,
func newAlwaysPanicMiddleware(message string) plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
func newAlwaysPanicMiddleware(message string) backend.HandlerMiddleware {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &alwaysErrorFuncMiddleware{func() error {
panic(message)
}}
@@ -6,25 +6,22 @@ import (
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/util/proxyutil"
)
// NewUserHeaderMiddleware creates a new plugins.ClientMiddleware that will
// populate the X-Grafana-User header on outgoing plugins.Client requests.
func NewUserHeaderMiddleware() plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
// NewUserHeaderMiddleware creates a new backend.HandlerMiddleware that will
// populate the X-Grafana-User header on outgoing backend.Handler requests.
func NewUserHeaderMiddleware() backend.HandlerMiddleware {
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
return &UserHeaderMiddleware{
baseMiddleware: baseMiddleware{
next: next,
},
BaseHandler: backend.NewBaseHandler(next),
}
})
}
type UserHeaderMiddleware struct {
baseMiddleware
backend.BaseHandler
}
func (m *UserHeaderMiddleware) applyUserHeader(ctx context.Context, h backend.ForwardHTTPHeaders) {
@@ -42,30 +39,30 @@ func (m *UserHeaderMiddleware) applyUserHeader(ctx context.Context, h backend.Fo
func (m *UserHeaderMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
if req == nil {
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
m.applyUserHeader(ctx, req)
return m.next.QueryData(ctx, req)
return m.BaseHandler.QueryData(ctx, req)
}
func (m *UserHeaderMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
if req == nil {
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
m.applyUserHeader(ctx, req)
return m.next.CallResource(ctx, req, sender)
return m.BaseHandler.CallResource(ctx, req, sender)
}
func (m *UserHeaderMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
if req == nil {
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
m.applyUserHeader(ctx, req)
return m.next.CheckHealth(ctx, req)
return m.BaseHandler.CheckHealth(ctx, req)
}
@@ -5,7 +5,7 @@ import (
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
"github.com/grafana/grafana-plugin-sdk-go/backend/handlertest"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/util/proxyutil"
"github.com/stretchr/testify/require"
@@ -17,12 +17,12 @@ func TestUserHeaderMiddleware(t *testing.T) {
require.NoError(t, err)
t.Run("And requests are for a datasource", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{
IsAnonymous: true,
Login: "anonymous"},
),
clienttest.WithMiddlewares(NewUserHeaderMiddleware()),
handlertest.WithMiddlewares(NewUserHeaderMiddleware()),
)
pluginCtx := backend.PluginContext{
@@ -30,7 +30,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
}
t.Run("Should not forward user header when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -40,7 +40,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
})
t.Run("Should not forward user header when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{},
}, nopCallResourceSender)
@@ -50,7 +50,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
})
t.Run("Should not forward user header when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -61,12 +61,12 @@ func TestUserHeaderMiddleware(t *testing.T) {
})
t.Run("And requests are for an app", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{
IsAnonymous: true,
Login: "anonymous"},
),
clienttest.WithMiddlewares(NewUserHeaderMiddleware()),
handlertest.WithMiddlewares(NewUserHeaderMiddleware()),
)
pluginCtx := backend.PluginContext{
@@ -74,7 +74,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
}
t.Run("Should not forward user header when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -84,7 +84,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
})
t.Run("Should not forward user header when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{},
}, nopCallResourceSender)
@@ -94,7 +94,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
})
t.Run("Should not forward user header when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -110,11 +110,11 @@ func TestUserHeaderMiddleware(t *testing.T) {
require.NoError(t, err)
t.Run("And requests are for a datasource", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{
Login: "admin",
}),
clienttest.WithMiddlewares(NewUserHeaderMiddleware()),
handlertest.WithMiddlewares(NewUserHeaderMiddleware()),
)
pluginCtx := backend.PluginContext{
@@ -122,7 +122,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
}
t.Run("Should forward user header when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -133,7 +133,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
})
t.Run("Should forward user header when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{},
}, nopCallResourceSender)
@@ -144,7 +144,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
})
t.Run("Should forward user header when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -156,11 +156,11 @@ func TestUserHeaderMiddleware(t *testing.T) {
})
t.Run("And requests are for an app", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{
cdt := handlertest.NewHandlerMiddlewareTest(t,
WithReqContext(req, &user.SignedInUser{
Login: "admin",
}),
clienttest.WithMiddlewares(NewUserHeaderMiddleware()),
handlertest.WithMiddlewares(NewUserHeaderMiddleware()),
)
pluginCtx := backend.PluginContext{
@@ -168,7 +168,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
}
t.Run("Should forward user header when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
_, err = cdt.MiddlewareHandler.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -179,7 +179,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
})
t.Run("Should forward user header when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
err = cdt.MiddlewareHandler.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{},
}, nopCallResourceSender)
@@ -190,7 +190,7 @@ func TestUserHeaderMiddleware(t *testing.T) {
})
t.Run("Should forward user header when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
_, err = cdt.MiddlewareHandler.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
@@ -3,6 +3,7 @@ package pluginsintegration
import (
"github.com/google/wire"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/prometheus/client_golang/prometheus"
"github.com/grafana/grafana/pkg/infra/tracing"
@@ -139,13 +140,13 @@ var WireExtensionSet = wire.NewSet(
wire.Bind(new(plugins.PluginLoaderAuthorizer), new(*signature.UnsignedPluginAuthorizer)),
finder.ProvideLocalFinder,
wire.Bind(new(finder.Finder), new(*finder.Local)),
ProvideClientDecorator,
wire.Bind(new(plugins.Client), new(*client.Decorator)),
ProvideClientWithMiddlewares,
wire.Bind(new(plugins.Client), new(*backend.MiddlewareHandler)),
managedplugins.NewNoop,
wire.Bind(new(managedplugins.Manager), new(*managedplugins.Noop)),
)
func ProvideClientDecorator(
func ProvideClientWithMiddlewares(
cfg *setting.Cfg,
pluginRegistry registry.Service,
oAuthTokenService oauthtoken.OAuthTokenService,
@@ -153,23 +154,23 @@ func ProvideClientDecorator(
cachingService caching.CachingService,
features featuremgmt.FeatureToggles,
promRegisterer prometheus.Registerer,
) (*client.Decorator, error) {
return NewClientDecorator(cfg, pluginRegistry, oAuthTokenService, tracer, cachingService, features, promRegisterer, pluginRegistry)
) (*backend.MiddlewareHandler, error) {
return NewMiddlewareHandler(cfg, pluginRegistry, oAuthTokenService, tracer, cachingService, features, promRegisterer, pluginRegistry)
}
func NewClientDecorator(
func NewMiddlewareHandler(
cfg *setting.Cfg,
pluginRegistry registry.Service, oAuthTokenService oauthtoken.OAuthTokenService,
tracer tracing.Tracer, cachingService caching.CachingService, features featuremgmt.FeatureToggles,
promRegisterer prometheus.Registerer, registry registry.Service,
) (*client.Decorator, error) {
) (*backend.MiddlewareHandler, error) {
c := client.ProvideService(pluginRegistry)
middlewares := CreateMiddlewares(cfg, oAuthTokenService, tracer, cachingService, features, promRegisterer, registry)
return client.NewDecorator(c, middlewares...)
return backend.HandlerFromMiddlewares(c, middlewares...)
}
func CreateMiddlewares(cfg *setting.Cfg, oAuthTokenService oauthtoken.OAuthTokenService, tracer tracing.Tracer, cachingService caching.CachingService, features featuremgmt.FeatureToggles, promRegisterer prometheus.Registerer, registry registry.Service) []plugins.ClientMiddleware {
middlewares := []plugins.ClientMiddleware{
func CreateMiddlewares(cfg *setting.Cfg, oAuthTokenService oauthtoken.OAuthTokenService, tracer tracing.Tracer, cachingService caching.CachingService, features featuremgmt.FeatureToggles, promRegisterer prometheus.Registerer, registry registry.Service) []backend.HandlerMiddleware {
middlewares := []backend.HandlerMiddleware{
clientmiddleware.NewPluginRequestMetaMiddleware(),
clientmiddleware.NewTracingMiddleware(tracer),
clientmiddleware.NewMetricsMiddleware(promRegisterer, registry),
@@ -187,7 +188,6 @@ func CreateMiddlewares(cfg *setting.Cfg, oAuthTokenService oauthtoken.OAuthToken
clientmiddleware.NewClearAuthHeadersMiddleware(),
clientmiddleware.NewOAuthTokenMiddleware(oAuthTokenService),
clientmiddleware.NewCookiesMiddleware(skipCookiesNames),
clientmiddleware.NewResourceResponseMiddleware(),
clientmiddleware.NewCachingMiddlewareWithFeatureManager(cachingService, features),
clientmiddleware.NewForwardIDMiddleware(),
)