Commit c3a19c6d by Andrej Ocenas Committed by GitHub

Influxdb: Fix issues with request creation and parsing (#21743)

parent 7569a860
...@@ -454,42 +454,9 @@ export class BackendSrv implements BackendService { ...@@ -454,42 +454,9 @@ export class BackendSrv implements BackendService {
return options; return options;
}; };
private parseUrlFromOptions = (options: BackendSrvRequest): string => {
const cleanParams = omitBy(options.params, v => v === undefined || (v && v.length === 0));
const serializedParams = serializeParams(cleanParams);
return options.params && serializedParams.length ? `${options.url}?${serializedParams}` : options.url;
};
private parseInitFromOptions = (options: BackendSrvRequest): RequestInit => {
const method = options.method;
const headers = {
'Content-Type': 'application/json',
Accept: 'application/json, text/plain, */*',
...options.headers,
};
const body = this.parseBody({ ...options, headers });
return {
method,
headers,
body,
};
};
private parseBody = (options: BackendSrvRequest) => {
if (!options.data || typeof options.data === 'string') {
return options.data;
}
if (options.headers['Content-Type'] === 'application/json') {
return JSON.stringify(options.data);
}
return new URLSearchParams(options.data);
};
private getFromFetchStream = (options: BackendSrvRequest) => { private getFromFetchStream = (options: BackendSrvRequest) => {
const url = this.parseUrlFromOptions(options); const url = parseUrlFromOptions(options);
const init = this.parseInitFromOptions(options); const init = parseInitFromOptions(options);
return this.dependencies.fromFetch(url, init).pipe( return this.dependencies.fromFetch(url, init).pipe(
mergeMap(async response => { mergeMap(async response => {
const { status, statusText, ok, headers, url, type, redirected } = response; const { status, statusText, ok, headers, url, type, redirected } = response;
...@@ -545,3 +512,36 @@ coreModule.factory('backendSrv', () => backendSrv); ...@@ -545,3 +512,36 @@ coreModule.factory('backendSrv', () => backendSrv);
// Used for testing and things that really need BackendSrv // Used for testing and things that really need BackendSrv
export const backendSrv = new BackendSrv(); export const backendSrv = new BackendSrv();
export const getBackendSrv = (): BackendSrv => backendSrv; export const getBackendSrv = (): BackendSrv => backendSrv;
export const parseUrlFromOptions = (options: BackendSrvRequest): string => {
const cleanParams = omitBy(options.params, v => v === undefined || (v && v.length === 0));
const serializedParams = serializeParams(cleanParams);
return options.params && serializedParams.length ? `${options.url}?${serializedParams}` : options.url;
};
export const parseInitFromOptions = (options: BackendSrvRequest): RequestInit => {
const method = options.method;
const headers = {
'Content-Type': 'application/json',
Accept: 'application/json, text/plain, */*',
...options.headers,
};
const body = parseBody({ ...options, headers });
return {
method,
headers,
body,
};
};
const parseBody = (options: BackendSrvRequest) => {
if (!options.data || typeof options.data === 'string') {
return options.data;
}
if (options.headers['Content-Type'] === 'application/json') {
return JSON.stringify(options.data);
}
return new URLSearchParams(options.data);
};
...@@ -81,6 +81,7 @@ export class InfluxLogsQueryField extends React.PureComponent<Props, State> { ...@@ -81,6 +81,7 @@ export class InfluxLogsQueryField extends React.PureComponent<Props, State> {
this.setState({ measurements }); this.setState({ measurements });
} catch (error) { } catch (error) {
const message = error && error.message ? error.message : error; const message = error && error.message ? error.message : error;
console.error(error);
this.setState({ error: message }); this.setState({ error: message });
} }
} }
......
...@@ -204,7 +204,9 @@ export default class InfluxDatasource extends DataSourceApi<InfluxQuery, InfluxO ...@@ -204,7 +204,9 @@ export default class InfluxDatasource extends DataSourceApi<InfluxQuery, InfluxO
metricFindQuery(query: string, options?: any) { metricFindQuery(query: string, options?: any) {
const interpolated = this.templateSrv.replace(query, null, 'regex'); const interpolated = this.templateSrv.replace(query, null, 'regex');
return this._seriesQuery(interpolated, options).then(() => this.responseParser.parse(query)); return this._seriesQuery(interpolated, options).then(resp => {
return this.responseParser.parse(query, resp);
});
} }
getTagKeys(options: any = {}) { getTagKeys(options: any = {}) {
...@@ -323,7 +325,7 @@ export default class InfluxDatasource extends DataSourceApi<InfluxQuery, InfluxO ...@@ -323,7 +325,7 @@ export default class InfluxDatasource extends DataSourceApi<InfluxQuery, InfluxO
return result.data; return result.data;
}, },
(err: any) => { (err: any) => {
if (err.status !== 0 || err.status >= 300) { if ((Number.isInteger(err.status) && err.status !== 0) || err.status >= 300) {
if (err.data && err.data.error) { if (err.data && err.data.error) {
throw { throw {
message: 'InfluxDB Error: ' + err.data.error, message: 'InfluxDB Error: ' + err.data.error,
...@@ -337,6 +339,8 @@ export default class InfluxDatasource extends DataSourceApi<InfluxQuery, InfluxO ...@@ -337,6 +339,8 @@ export default class InfluxDatasource extends DataSourceApi<InfluxQuery, InfluxO
config: err.config, config: err.config,
}; };
} }
} else {
throw err;
} }
} }
); );
......
...@@ -31,7 +31,7 @@ describe('InfluxDataSource', () => { ...@@ -31,7 +31,7 @@ describe('InfluxDataSource', () => {
to: '2018-01-02T00:00:00Z', to: '2018-01-02T00:00:00Z',
}, },
}; };
let requestQuery: any, requestMethod: any, requestData: any; let requestQuery: any, requestMethod: any, requestData: any, response: any;
beforeEach(async () => { beforeEach(async () => {
datasourceRequestMock.mockImplementation((req: any) => { datasourceRequestMock.mockImplementation((req: any) => {
...@@ -39,21 +39,23 @@ describe('InfluxDataSource', () => { ...@@ -39,21 +39,23 @@ describe('InfluxDataSource', () => {
requestQuery = req.params.q; requestQuery = req.params.q;
requestData = req.data; requestData = req.data;
return Promise.resolve({ return Promise.resolve({
results: [ data: {
{ results: [
series: [ {
{ series: [
name: 'measurement', {
columns: ['max'], name: 'measurement',
values: [[1]], columns: ['name'],
}, values: [['cpu']],
], },
}, ],
], },
],
},
}); });
}); });
await ctx.ds.metricFindQuery(query, queryOptions).then(() => {}); response = await ctx.ds.metricFindQuery(query, queryOptions);
}); });
it('should replace $timefilter', () => { it('should replace $timefilter', () => {
...@@ -67,6 +69,10 @@ describe('InfluxDataSource', () => { ...@@ -67,6 +69,10 @@ describe('InfluxDataSource', () => {
it('should not have any data in request body', () => { it('should not have any data in request body', () => {
expect(requestData).toBeNull(); expect(requestData).toBeNull();
}); });
it('parse response correctly', () => {
expect(response).toEqual([{ text: 'cpu' }]);
});
}); });
describe('InfluxDataSource in POST query mode', () => { describe('InfluxDataSource in POST query mode', () => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment