mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
@grafana/data
: Add serializeParams
(#78468)
* Move serializeParams to @grafana/data * Update comment * Update solution in Tempo * Fix type assertions * Use toUrlParams in serializeParams * Update data sources * Update * Update packages/grafana-data/src/utils/url.ts
This commit is contained in:
parent
9a3b2937aa
commit
02090f71d2
@ -6486,11 +6486,9 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Do not use any type assertions.", "4"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "6"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "7"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "8"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "9"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "10"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "11"]
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "8"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "9"]
|
||||
],
|
||||
"public/app/plugins/datasource/tempo/language_provider.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
|
@ -33,6 +33,36 @@ describe('toUrlParams', () => {
|
||||
});
|
||||
expect(url).toBe('datasource=testDs%5B%21%27%28%29%2A%5D');
|
||||
});
|
||||
it('should encode object properties as url parameters', () => {
|
||||
const params = urlUtil.serializeParams({
|
||||
server: 'backend-01',
|
||||
hasSpace: 'has space',
|
||||
many: ['1', '2', '3'],
|
||||
true: true,
|
||||
number: 20,
|
||||
isNull: null,
|
||||
isUndefined: undefined,
|
||||
oneMore: false,
|
||||
});
|
||||
expect(params).toBe(
|
||||
'server=backend-01&hasSpace=has%20space&many=1&many=2&many=3&true&number=20&isNull=&isUndefined=&oneMore=false'
|
||||
);
|
||||
});
|
||||
|
||||
it('should not encode special character the same way as angular js', () => {
|
||||
const params = urlUtil.serializeParams({
|
||||
server: ':@',
|
||||
});
|
||||
expect(params).not.toBe('server=:@');
|
||||
});
|
||||
|
||||
it('should keep booleans', () => {
|
||||
const url = urlUtil.serializeParams({
|
||||
bool1: true,
|
||||
bool2: false,
|
||||
});
|
||||
expect(url).toBe('bool1&bool2=false');
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseKeyValue', () => {
|
||||
|
@ -27,7 +27,7 @@ function renderUrl(path: string, query: UrlQueryMap | undefined): string {
|
||||
return path;
|
||||
}
|
||||
|
||||
function encodeURIComponentAsAngularJS(val: string, pctEncodeSpaces?: boolean) {
|
||||
function encodeURIComponentAsAngularJS(val: EncodeURIComponentParams, pctEncodeSpaces?: boolean) {
|
||||
return encodeURIComponent(val)
|
||||
.replace(/%40/gi, '@')
|
||||
.replace(/%3A/gi, ':')
|
||||
@ -40,10 +40,20 @@ function encodeURIComponentAsAngularJS(val: string, pctEncodeSpaces?: boolean) {
|
||||
});
|
||||
}
|
||||
|
||||
function toUrlParams(a: any) {
|
||||
type EncodeURIComponentParams = Parameters<typeof encodeURIComponent>[0];
|
||||
/**
|
||||
* Encodes URL parameters in the style of AngularJS.
|
||||
* Use `serializeParams` to encode parameters using `encodeURIComponent` instead.
|
||||
*/
|
||||
function toUrlParams(a: any, encodeAsAngularJS = true) {
|
||||
const s: any[] = [];
|
||||
const rbracket = /\[\]$/;
|
||||
|
||||
const encodingFunction = encodeAsAngularJS
|
||||
? (value: EncodeURIComponentParams, pctEncodeSpaces?: boolean) =>
|
||||
encodeURIComponentAsAngularJS(value, pctEncodeSpaces)
|
||||
: (value: EncodeURIComponentParams, _: boolean) => encodeURIComponent(value);
|
||||
|
||||
const isArray = (obj: any) => {
|
||||
return Object.prototype.toString.call(obj) === '[object Array]';
|
||||
};
|
||||
@ -51,10 +61,10 @@ function toUrlParams(a: any) {
|
||||
const add = (k: string, v: any) => {
|
||||
v = typeof v === 'function' ? v() : v === null ? '' : v === undefined ? '' : v;
|
||||
if (typeof v !== 'boolean') {
|
||||
s[s.length] = encodeURIComponentAsAngularJS(k, true) + '=' + encodeURIComponentAsAngularJS(v, true);
|
||||
s[s.length] = encodingFunction(k, true) + '=' + encodingFunction(v, true);
|
||||
} else {
|
||||
const valueQueryPart = v ? '' : '=' + encodeURIComponentAsAngularJS('false', true);
|
||||
s[s.length] = encodeURIComponentAsAngularJS(k, true) + valueQueryPart;
|
||||
const valueQueryPart = v ? '' : '=' + encodingFunction('false', true);
|
||||
s[s.length] = encodingFunction(k, true) + valueQueryPart;
|
||||
}
|
||||
};
|
||||
|
||||
@ -92,6 +102,16 @@ function toUrlParams(a: any) {
|
||||
return buildParams('', a).join('&');
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts params into a URL-encoded query string.
|
||||
*
|
||||
* @param params data to serialize
|
||||
* @returns A URL-encoded string representing the provided data.
|
||||
*/
|
||||
function serializeParams(params: unknown): string {
|
||||
return toUrlParams(params, false);
|
||||
}
|
||||
|
||||
function appendQueryToUrl(url: string, stringToAppend: string) {
|
||||
if (stringToAppend !== undefined && stringToAppend !== null && stringToAppend !== '') {
|
||||
const pos = url.indexOf('?');
|
||||
@ -198,6 +218,7 @@ export const urlUtil = {
|
||||
appendQueryToUrl,
|
||||
getUrlSearchParams,
|
||||
parseKeyValue,
|
||||
serializeParams,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -130,7 +130,7 @@ export async function parseResponseBody<T>(
|
||||
return textData as any;
|
||||
}
|
||||
|
||||
export function serializeParams(data: Record<string, any>): string {
|
||||
function serializeParams(data: Record<string, any>): string {
|
||||
return Object.keys(data)
|
||||
.map((key) => {
|
||||
const value = data[key];
|
||||
|
@ -13,10 +13,10 @@ import {
|
||||
FieldType,
|
||||
MutableDataFrame,
|
||||
ScopedVars,
|
||||
urlUtil,
|
||||
} from '@grafana/data';
|
||||
import { BackendSrvRequest, getBackendSrv, getTemplateSrv, TemplateSrv } from '@grafana/runtime';
|
||||
import { NodeGraphOptions } from 'app/core/components/NodeGraphSettings';
|
||||
import { serializeParams } from 'app/core/utils/fetch';
|
||||
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
import { SpanBarOptions } from 'app/features/explore/TraceView/components';
|
||||
|
||||
@ -235,7 +235,7 @@ export class JaegerDatasource extends DataSourceApi<JaegerQuery, JaegerJsonData>
|
||||
data?: Record<string, unknown>,
|
||||
options?: Partial<BackendSrvRequest>
|
||||
): Observable<Record<string, any>> {
|
||||
const params = data ? serializeParams(data) : '';
|
||||
const params = data ? urlUtil.serializeParams(data) : '';
|
||||
const url = `${this.instanceSettings.url}${apiUrl}${params.length ? `?${params}` : ''}`;
|
||||
const req = {
|
||||
...options,
|
||||
|
@ -36,6 +36,7 @@ import {
|
||||
renderLegendFormat,
|
||||
LegacyMetricFindQueryOptions,
|
||||
AdHocVariableFilter,
|
||||
urlUtil,
|
||||
} from '@grafana/data';
|
||||
import { Duration } from '@grafana/lezer-logql';
|
||||
import { BackendSrvRequest, config, DataSourceWithBackend, getTemplateSrv, TemplateSrv } from '@grafana/runtime';
|
||||
@ -43,7 +44,6 @@ import { DataQuery } from '@grafana/schema';
|
||||
import { convertToWebSocketUrl } from 'app/core/utils/explore';
|
||||
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
|
||||
import { serializeParams } from '../../../core/utils/fetch';
|
||||
import { queryLogsSample, queryLogsVolume } from '../../../features/logs/logsModel';
|
||||
import { getLogLevelFromKey } from '../../../features/logs/utils';
|
||||
import { replaceVariables, returnVariables } from '../prometheus/querybuilder/shared/parsingUtils';
|
||||
@ -384,7 +384,7 @@ export class LokiDatasource
|
||||
private createLiveTarget(target: LokiQuery, maxDataPoints: number): LokiLiveTarget {
|
||||
const query = target.expr;
|
||||
const baseUrl = this.instanceSettings.url;
|
||||
const params = serializeParams({ query });
|
||||
const params = urlUtil.serializeParams({ query });
|
||||
|
||||
return {
|
||||
query,
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
rangeUtil,
|
||||
ScopedVars,
|
||||
TestDataSourceResponse,
|
||||
urlUtil,
|
||||
} from '@grafana/data';
|
||||
import {
|
||||
BackendSrvRequest,
|
||||
@ -32,7 +33,6 @@ import {
|
||||
import { BarGaugeDisplayMode, TableCellDisplayMode, VariableFormatID } from '@grafana/schema';
|
||||
import { NodeGraphOptions } from 'app/core/components/NodeGraphSettings';
|
||||
import { TraceToLogsOptions } from 'app/core/components/TraceToLogs/TraceToLogsSettings';
|
||||
import { serializeParams } from 'app/core/utils/fetch';
|
||||
import { SpanBarOptions } from 'app/features/explore/TraceView/components';
|
||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||
|
||||
@ -691,7 +691,7 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
|
||||
data?: unknown,
|
||||
options?: Partial<BackendSrvRequest>
|
||||
): Observable<Record<string, any>> {
|
||||
const params = data ? serializeParams(data) : '';
|
||||
const params = data ? urlUtil.serializeParams(data) : '';
|
||||
const url = `${this.instanceSettings.url}${apiUrl}${params.length ? `?${params}` : ''}`;
|
||||
const req = { ...options, url };
|
||||
|
||||
@ -723,7 +723,9 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
|
||||
if (query.queryType === 'nativeSearch') {
|
||||
let result = [];
|
||||
for (const key of ['serviceName', 'spanName', 'search', 'minDuration', 'maxDuration', 'limit']) {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
if (query.hasOwnProperty(key) && query[key as keyof TempoQuery]) {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
result.push(`${startCase(key)}: ${query[key as keyof TempoQuery]}`);
|
||||
}
|
||||
}
|
||||
|
@ -10,13 +10,12 @@ import {
|
||||
FieldType,
|
||||
createDataFrame,
|
||||
ScopedVars,
|
||||
urlUtil,
|
||||
} from '@grafana/data';
|
||||
import { BackendSrvRequest, FetchResponse, getBackendSrv, getTemplateSrv, TemplateSrv } from '@grafana/runtime';
|
||||
import { NodeGraphOptions } from 'app/core/components/NodeGraphSettings';
|
||||
import { SpanBarOptions } from 'app/features/explore/TraceView/components';
|
||||
|
||||
import { serializeParams } from '../../../core/utils/fetch';
|
||||
|
||||
import { apiPrefix } from './constants';
|
||||
import { ZipkinQuery, ZipkinSpan } from './types';
|
||||
import { createGraphFrames } from './utils/graphTransform';
|
||||
@ -104,7 +103,7 @@ export class ZipkinDatasource extends DataSourceApi<ZipkinQuery, ZipkinJsonData>
|
||||
data?: any,
|
||||
options?: Partial<BackendSrvRequest>
|
||||
): Observable<FetchResponse<T>> {
|
||||
const params = data ? serializeParams(data) : '';
|
||||
const params = data ? urlUtil.serializeParams(data) : '';
|
||||
const url = `${this.instanceSettings.url}${apiUrl}${params.length ? `?${params}` : ''}`;
|
||||
const req = {
|
||||
...options,
|
||||
|
Loading…
Reference in New Issue
Block a user