grafana/pkg/services/datasourceproxy/datasourceproxy_test.go
Kyle Brandt e4d1fdc3d0
Errors: Make errors the same in dev as prod (#77366)
When running in dev mode, error messages would contain an additional "error" property alongside "message". Since this causes confusion, that has been removed and now error messages are the same both modes (using "message").
2023-10-30 14:06:26 -04:00

133 lines
3.2 KiB
Go

package datasourceproxy
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
"github.com/grafana/grafana/pkg/web"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestDataProxy(t *testing.T) {
t.Run("extractProxyPath", func(t *testing.T) {
testCases := []struct {
originalRawPath string
exp string
}{
{
"/api/datasources/proxy/1",
"",
},
{
"/api/datasources/proxy/1/some/thing",
"some/thing",
},
{
"/api/datasources/proxy/54/api/services/afsd%2Fafsd/operations",
"api/services/afsd%2Fafsd/operations",
},
{
"/api/datasources/proxy/uid/26MI0wZ7k",
"",
},
{
"/api/datasources/proxy/uid/26MI0wZ7k/some/thing",
"some/thing",
},
{
"/api/datasources/proxy/uid/pUWo-no4k/search",
"search",
},
{
"/api/datasources/proxy/uid/pUWo_no4k/search",
"search",
},
{
"/api/datasources/proxy/uid/26MI0wZ7k/api/services/afsd%2Fafsd/operations",
"api/services/afsd%2Fafsd/operations",
},
}
for _, tc := range testCases {
t.Run("Given raw path, should extract expected proxy path", func(t *testing.T) {
assert.Equal(t, tc.exp, extractProxyPath(tc.originalRawPath))
})
}
})
}
// Tests request to datasource proxy service
func TestDatasourceProxy_proxyDatasourceRequest(t *testing.T) {
tcs := []struct {
name string
dsURL string
}{
{
name: "Empty datasource URL will return a 400 HTTP status code",
dsURL: "",
},
{
name: "Invalid datasource URL will return a 400 HTTP status code",
dsURL: "://host/path",
},
}
for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
pluginID := datasources.DS_PROMETHEUS
pluginStore := &pluginstore.FakePluginStore{PluginList: []pluginstore.Plugin{
{JSONData: plugins.JSONData{ID: pluginID}},
}}
p := DataSourceProxyService{
PluginRequestValidator: &fakePluginRequestValidator{},
pluginStore: pluginStore,
}
responseRecorder := httptest.NewRecorder()
c := &contextmodel.ReqContext{
Context: &web.Context{
Req: &http.Request{URL: &url.URL{}},
Resp: web.NewResponseWriter("GET", responseRecorder),
},
Logger: log.NewNopLogger(),
}
p.proxyDatasourceRequest(c, &datasources.DataSource{
Type: pluginID,
URL: tc.dsURL,
})
resp := responseRecorder.Result()
body := resp.Body
b, err := io.ReadAll(body)
require.NoError(t, err)
require.NoError(t, body.Close())
jsonBody := make(map[string]string)
err = json.Unmarshal(b, &jsonBody)
require.NoError(t, err)
require.Equal(t, http.StatusBadRequest, resp.StatusCode)
require.Equal(t, fmt.Sprintf("Invalid data source URL: %q", tc.dsURL), jsonBody["message"])
})
}
}
type fakePluginRequestValidator struct{}
func (rv *fakePluginRequestValidator) Validate(_ string, _ *http.Request) error {
return nil
}