mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-11 09:51:30 +00:00
fix(app): preserve colons in OData datetimes (#7415)
This commit is contained in:
@@ -12,6 +12,32 @@ const hasLength = (str) => {
|
||||
return str.length > 0;
|
||||
};
|
||||
|
||||
const ODATA_PATH_PARAM_REGEX = /(^|[=(,'"`]):([A-Za-z_]\w*)\b/g;
|
||||
|
||||
const decodeODataSegment = (segment) => {
|
||||
try {
|
||||
return decodeURIComponent(segment);
|
||||
} catch (error) {
|
||||
return segment;
|
||||
}
|
||||
};
|
||||
|
||||
const getODataPathParamNames = (segment) => {
|
||||
const names = [];
|
||||
const decodedSegment = decodeODataSegment(segment);
|
||||
let match;
|
||||
|
||||
while ((match = ODATA_PATH_PARAM_REGEX.exec(decodedSegment))) {
|
||||
if (match[2]) {
|
||||
names.push(match[2]);
|
||||
}
|
||||
}
|
||||
|
||||
ODATA_PATH_PARAM_REGEX.lastIndex = 0;
|
||||
|
||||
return names;
|
||||
};
|
||||
|
||||
export const parsePathParams = (url) => {
|
||||
let uri = url.slice();
|
||||
|
||||
@@ -49,17 +75,12 @@ export const parsePathParams = (url) => {
|
||||
// 1. EntitySet('key') or EntitySet(key)
|
||||
// 2. EntitySet(Key1=value1,Key2=value2)
|
||||
// 3. Function(param=value)
|
||||
if (!/^[A-Za-z0-9_.-]+\([^)]*\)$/.test(segment)) {
|
||||
if (!/^[A-Za-z0-9_.-]+\([^)]*\)$/.test(decodeODataSegment(segment))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const paramRegex = /[:](\w+)/g;
|
||||
let match;
|
||||
while ((match = paramRegex.exec(segment))) {
|
||||
if (!match[1]) continue;
|
||||
|
||||
let name = match[1].replace(/[')"`]+$/, '');
|
||||
name = name.replace(/^[('"`]+/, '');
|
||||
const paramNames = getODataPathParamNames(segment);
|
||||
for (const name of paramNames) {
|
||||
if (name && !foundParams.has(name)) {
|
||||
foundParams.add(name);
|
||||
}
|
||||
@@ -127,23 +148,18 @@ export const interpolateUrlPathParams = (url, params, variables = {}, options =
|
||||
// 1. EntitySet('key') or EntitySet(key)
|
||||
// 2. EntitySet(Key1=value1,Key2=value2)
|
||||
// 3. Function(param=value)
|
||||
if (!/^[A-Za-z0-9_.-]+\([^)]*\)$/.test(segment)) {
|
||||
if (!/^[A-Za-z0-9_.-]+\([^)]*\)$/.test(decodeODataSegment(segment))) {
|
||||
return segment;
|
||||
}
|
||||
|
||||
const regex = /[:](\w+)/g;
|
||||
let match;
|
||||
let result = segment;
|
||||
while ((match = regex.exec(segment))) {
|
||||
if (!match[1]) continue;
|
||||
|
||||
let name = match[1].replace(/[')"`]+$/, '');
|
||||
name = name.replace(/^[('"`]+/, '');
|
||||
const paramNames = getODataPathParamNames(segment);
|
||||
for (const name of paramNames) {
|
||||
if (!name) continue;
|
||||
|
||||
const pathParam = params.find((p) => p?.name === name && p?.type === 'path');
|
||||
if (pathParam) {
|
||||
result = result.replace(':' + match[1], pathParam.value);
|
||||
result = result.replace(`:${name}`, pathParam.value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -259,6 +259,14 @@ describe('Url Utils - OData parameters', () => {
|
||||
const params = parsePathParams('https://example.com/odata/Products?$filter=Category eq \'{{category}}\'&$orderby={{sortField}}');
|
||||
expect(params).toEqual([]);
|
||||
});
|
||||
|
||||
it('should not treat colons inside OData datetime values as path params', () => {
|
||||
const params = parsePathParams(
|
||||
'https://api10.successfactors.com/odata/v2/EmpJob(seqNumber=1L,startDate=datetime\'2021-08-29T00:00:00\',userId=\'213668\')?$format=json'
|
||||
);
|
||||
|
||||
expect(params).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Url Utils - splitOnFirst', () => {
|
||||
@@ -463,4 +471,28 @@ describe('Url Utils - interpolateUrlPathParams with { raw: true }', () => {
|
||||
|
||||
expect(result).toEqual('https://example.com/api/:id');
|
||||
});
|
||||
|
||||
it('should preserve OData datetime colons when no path params are present', () => {
|
||||
const url
|
||||
= 'https://api10.successfactors.com/odata/v2/EmpJob(seqNumber=1L,startDate=datetime\'2021-08-29T00:00:00\',userId=\'213668\')?$format=json';
|
||||
|
||||
const result = interpolateUrlPathParams(url, [], {}, { raw: true });
|
||||
|
||||
expect(result).toEqual(url);
|
||||
});
|
||||
|
||||
it('should replace only real OData path params and preserve datetime colons', () => {
|
||||
const url
|
||||
= 'https://example.com/odata/v2/EmpJob(seqNumber=:seqNumber,startDate=datetime\'2021-08-29T00:00:00\',userId=\':userId\')?$format=json';
|
||||
const params = [
|
||||
{ name: 'seqNumber', type: 'path', enabled: true, value: '1L' },
|
||||
{ name: 'userId', type: 'path', enabled: true, value: '213668' }
|
||||
];
|
||||
|
||||
const result = interpolateUrlPathParams(url, params, {}, { raw: true });
|
||||
|
||||
expect(result).toEqual(
|
||||
'https://example.com/odata/v2/EmpJob(seqNumber=1L,startDate=datetime\'2021-08-29T00:00:00\',userId=\'213668\')?$format=json'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user