mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Prometheus: Use configured HTTP method for /series and /labels endpoints (#31401)
* Run post-friendly request with set method first * Improve messaging, retry only when post and specific status code * Add comments * Fix backend * Update public/app/plugins/datasource/prometheus/datasource.ts
This commit is contained in:
parent
6d1076fca7
commit
dce67db6ba
@ -245,8 +245,8 @@ func (proxy *DataSourceProxy) validateRequest() error {
|
||||
if proxy.ctx.Req.Request.Method == "PUT" {
|
||||
return errors.New("puts not allowed on proxied Prometheus datasource")
|
||||
}
|
||||
if proxy.ctx.Req.Request.Method == "POST" && !(proxy.proxyPath == "api/v1/query" || proxy.proxyPath == "api/v1/query_range") {
|
||||
return errors.New("posts not allowed on proxied Prometheus datasource except on /query and /query_range")
|
||||
if proxy.ctx.Req.Request.Method == "POST" && !(proxy.proxyPath == "api/v1/query" || proxy.proxyPath == "api/v1/query_range" || proxy.proxyPath == "api/v1/series" || proxy.proxyPath == "api/v1/labels") {
|
||||
return errors.New("posts not allowed on proxied Prometheus datasource except on /query, /query_range, /series and /labels")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,8 +105,7 @@ describe('PrometheusDatasource', () => {
|
||||
expect(fetchMock.mock.calls.length).toBe(1);
|
||||
expect(fetchMock.mock.calls[0][0].method).toBe('GET');
|
||||
});
|
||||
|
||||
it('should still perform a GET request with the DS HTTP method set to POST', () => {
|
||||
it('should still perform a GET request with the DS HTTP method set to POST and not POST-friendly endpoint', () => {
|
||||
const postSettings = _.cloneDeep(instanceSettings);
|
||||
postSettings.jsonData.httpMethod = 'POST';
|
||||
const promDs = new PrometheusDatasource(postSettings, templateSrvStub as any, timeSrvStub as any);
|
||||
@ -114,6 +113,14 @@ describe('PrometheusDatasource', () => {
|
||||
expect(fetchMock.mock.calls.length).toBe(1);
|
||||
expect(fetchMock.mock.calls[0][0].method).toBe('GET');
|
||||
});
|
||||
it('should try to perform a POST request with the DS HTTP method set to POST and POST-friendly endpoint', () => {
|
||||
const postSettings = _.cloneDeep(instanceSettings);
|
||||
postSettings.jsonData.httpMethod = 'POST';
|
||||
const promDs = new PrometheusDatasource(postSettings, templateSrvStub as any, timeSrvStub as any);
|
||||
promDs.metadataRequest('api/v1/series');
|
||||
expect(fetchMock.mock.calls.length).toBe(1);
|
||||
expect(fetchMock.mock.calls[0][0].method).toBe('POST');
|
||||
});
|
||||
});
|
||||
|
||||
describe('When using customQueryParams', () => {
|
||||
|
@ -44,6 +44,7 @@ import { PrometheusVariableSupport } from './variables';
|
||||
import PrometheusMetricFindQuery from './metric_find_query';
|
||||
|
||||
export const ANNOTATION_QUERY_STEP_DEFAULT = '60s';
|
||||
const GET_AND_POST_MEDATADATA_ENDPOINTS = ['api/v1/query', 'api/v1/query_range', 'api/v1/series', 'api/v1/labels'];
|
||||
|
||||
export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions> {
|
||||
type: string;
|
||||
@ -136,7 +137,7 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
|
||||
}
|
||||
|
||||
// Use this for tab completion features, wont publish response to other components
|
||||
metadataRequest<T = any>(url: string) {
|
||||
async metadataRequest<T = any>(url: string) {
|
||||
const data: any = {};
|
||||
for (const [key, value] of this.customQueryParameters) {
|
||||
if (data[key] == null) {
|
||||
@ -144,7 +145,21 @@ export class PrometheusDatasource extends DataSourceApi<PromQuery, PromOptions>
|
||||
}
|
||||
}
|
||||
|
||||
return this._request<T>(url, data, { method: 'GET', hideFromInspector: true }).toPromise(); // toPromise until we change getTagValues, getTagKeys to Observable
|
||||
// If URL includes endpoint that supports POST and GET method, try to use configured method. This might fail as POST is supported only in v2.10+.
|
||||
if (GET_AND_POST_MEDATADATA_ENDPOINTS.some((endpoint) => url.includes(endpoint))) {
|
||||
try {
|
||||
return await this._request<T>(url, data, { method: this.httpMethod, hideFromInspector: true }).toPromise();
|
||||
} catch (err) {
|
||||
// If status code of error is Method Not Allowed (405) and HTTP method is POST, retry with GET
|
||||
if (this.httpMethod === 'POST' && err.status === 405) {
|
||||
console.warn(`Couldn't use configured POST HTTP method for this request. Trying to use GET method instead.`);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await this._request<T>(url, data, { method: 'GET', hideFromInspector: true }).toPromise(); // toPromise until we change getTagValues, getTagKeys to Observable
|
||||
}
|
||||
|
||||
interpolateQueryExpr(value: string | string[] = [], variable: any) {
|
||||
|
Loading…
Reference in New Issue
Block a user