mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
CallResource: don't set Content-Type header if status is 204 (#50780)
Grafana's HTTPServer ensures that the Content-Type header is always set in the response to a CallResource call, but when the status code is 204 No Content this shouldn't be done; the body should be empty and no Content-Type header should be set. We ran into this in the Grafana ML plugin where we were sending an empty response with status 204, but the frontend client saw that the content type was JSON and tried to parse it, resulting in an error that made it to the JS console.
This commit is contained in:
parent
43436bd6f0
commit
480277f612
@ -193,7 +193,7 @@ func (hs *HTTPServer) flushStream(stream callResourceClientResponseStream, w htt
|
||||
// Expected that headers and status are only part of first stream
|
||||
if processedStreams == 0 && resp.Headers != nil {
|
||||
// Make sure a content type always is returned in response
|
||||
if _, exists := resp.Headers["Content-Type"]; !exists {
|
||||
if _, exists := resp.Headers["Content-Type"]; !exists && resp.Status != http.StatusNoContent {
|
||||
resp.Headers["Content-Type"] = []string{"application/json"}
|
||||
}
|
||||
|
||||
|
@ -331,10 +331,35 @@ func TestMakePluginResourceRequest(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
require.Equal(t, resp.Header().Get("Content-Type"), "application/json")
|
||||
require.Equal(t, "sandbox", resp.Header().Get("Content-Security-Policy"))
|
||||
require.Empty(t, req.Header.Get(customHeader))
|
||||
}
|
||||
|
||||
func TestMakePluginResourceRequestContentTypeEmpty(t *testing.T) {
|
||||
pluginClient := &fakePluginClient{
|
||||
statusCode: http.StatusNoContent,
|
||||
}
|
||||
hs := HTTPServer{
|
||||
Cfg: setting.NewCfg(),
|
||||
log: log.New(),
|
||||
pluginClient: pluginClient,
|
||||
}
|
||||
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
pCtx := backend.PluginContext{}
|
||||
err := hs.makePluginResourceRequest(resp, req, pCtx)
|
||||
require.NoError(t, err)
|
||||
|
||||
for {
|
||||
if resp.Flushed {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
require.Zero(t, resp.Header().Get("Content-Type"))
|
||||
}
|
||||
|
||||
func callGetPluginAsset(sc *scenarioContext) {
|
||||
sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec()
|
||||
}
|
||||
@ -366,6 +391,8 @@ type fakePluginClient struct {
|
||||
req *backend.CallResourceRequest
|
||||
|
||||
backend.QueryDataHandlerFunc
|
||||
|
||||
statusCode int
|
||||
}
|
||||
|
||||
func (c *fakePluginClient) CallResource(_ context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||
@ -377,8 +404,13 @@ func (c *fakePluginClient) CallResource(_ context.Context, req *backend.CallReso
|
||||
return err
|
||||
}
|
||||
|
||||
statusCode := http.StatusOK
|
||||
if c.statusCode != 0 {
|
||||
statusCode = c.statusCode
|
||||
}
|
||||
|
||||
return sender.Send(&backend.CallResourceResponse{
|
||||
Status: http.StatusOK,
|
||||
Status: statusCode,
|
||||
Headers: make(map[string][]string),
|
||||
Body: bytes,
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user