mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-24 17:48:30 +02:00
Fix curl import: decode Unicode escape sequences in $'...' strings (#318)
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -55,6 +55,34 @@ export const plugin: PluginDefinition = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes escape sequences in shell $'...' strings
|
||||||
|
* Handles Unicode escape sequences (\uXXXX) and common escape codes
|
||||||
|
*/
|
||||||
|
function decodeShellString(str: string): string {
|
||||||
|
return str
|
||||||
|
.replace(/\\u([0-9a-fA-F]{4})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
||||||
|
.replace(/\\x([0-9a-fA-F]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
||||||
|
.replace(/\\n/g, '\n')
|
||||||
|
.replace(/\\r/g, '\r')
|
||||||
|
.replace(/\\t/g, '\t')
|
||||||
|
.replace(/\\'/g, "'")
|
||||||
|
.replace(/\\"/g, '"')
|
||||||
|
.replace(/\\\\/g, '\\');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a string might contain escape sequences that need decoding
|
||||||
|
* If so, decodes them; otherwise returns the string as-is
|
||||||
|
*/
|
||||||
|
function maybeDecodeEscapeSequences(str: string): string {
|
||||||
|
// Check if the string contains escape sequences that shell-quote might not handle
|
||||||
|
if (str.includes('\\u') || str.includes('\\x')) {
|
||||||
|
return decodeShellString(str);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
export function convertCurl(rawData: string) {
|
export function convertCurl(rawData: string) {
|
||||||
if (!rawData.match(/^\s*curl /)) {
|
if (!rawData.match(/^\s*curl /)) {
|
||||||
return null;
|
return null;
|
||||||
@@ -86,9 +114,11 @@ export function convertCurl(rawData: string) {
|
|||||||
for (const parseEntry of normalizedParseEntries) {
|
for (const parseEntry of normalizedParseEntries) {
|
||||||
if (typeof parseEntry === 'string') {
|
if (typeof parseEntry === 'string') {
|
||||||
if (parseEntry.startsWith('$')) {
|
if (parseEntry.startsWith('$')) {
|
||||||
currentCommand.push(parseEntry.slice(1));
|
// Handle $'...' strings from shell-quote - decode escape sequences
|
||||||
|
currentCommand.push(decodeShellString(parseEntry.slice(1)));
|
||||||
} else {
|
} else {
|
||||||
currentCommand.push(parseEntry);
|
// Decode escape sequences that shell-quote might not handle
|
||||||
|
currentCommand.push(maybeDecodeEscapeSequences(parseEntry));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -108,7 +138,7 @@ export function convertCurl(rawData: string) {
|
|||||||
|
|
||||||
if (op?.startsWith('$')) {
|
if (op?.startsWith('$')) {
|
||||||
// Handle the case where literal like -H $'Header: \'Some Quoted Thing\''
|
// Handle the case where literal like -H $'Header: \'Some Quoted Thing\''
|
||||||
const str = op.slice(2, op.length - 1).replace(/\\'/g, "'");
|
const str = decodeShellString(op.slice(2, op.length - 1));
|
||||||
|
|
||||||
currentCommand.push(str);
|
currentCommand.push(str);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -391,6 +391,56 @@ describe('importer-curl', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Imports data with Unicode escape sequences', () => {
|
||||||
|
expect(
|
||||||
|
convertCurl(
|
||||||
|
`curl 'https://yaak.app' -H 'Content-Type: application/json' --data-raw $'{"query":"SearchQueryInput\\u0021"}' -X POST`,
|
||||||
|
),
|
||||||
|
).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
method: 'POST',
|
||||||
|
headers: [{ name: 'Content-Type', value: 'application/json', enabled: true }],
|
||||||
|
bodyType: 'application/json',
|
||||||
|
body: { text: '{"query":"SearchQueryInput!"}' },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Imports data with multiple escape sequences', () => {
|
||||||
|
expect(
|
||||||
|
convertCurl(
|
||||||
|
`curl 'https://yaak.app' --data-raw $'Line1\\nLine2\\tTab\\u0021Exclamation' -X POST`,
|
||||||
|
),
|
||||||
|
).toEqual({
|
||||||
|
resources: {
|
||||||
|
workspaces: [baseWorkspace()],
|
||||||
|
httpRequests: [
|
||||||
|
baseRequest({
|
||||||
|
url: 'https://yaak.app',
|
||||||
|
method: 'POST',
|
||||||
|
bodyType: 'application/x-www-form-urlencoded',
|
||||||
|
body: {
|
||||||
|
form: [{ name: 'Line1\nLine2\tTab!Exclamation', value: '', enabled: true }],
|
||||||
|
},
|
||||||
|
headers: [
|
||||||
|
{
|
||||||
|
enabled: true,
|
||||||
|
name: 'Content-Type',
|
||||||
|
value: 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const idCount: Partial<Record<string, number>> = {};
|
const idCount: Partial<Record<string, number>> = {};
|
||||||
|
|||||||
Reference in New Issue
Block a user