Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes issue where cURL in Windows cmd formats were not imported correctly. #53

Merged
merged 3 commits into from
Feb 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 53 additions & 4 deletions src/lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,13 @@ var program,
curlObj.dataBinary || curlObj.dataUrlencode.length > 0) &&
curlObj.head && !curlObj.get) {
throw new Error('Error while parsing cURL: Both (--head/-I) and' +
'(-d/--data/--data-raw/--data-binary/--data-ascii/--data-urlencode) are not supported');
' (-d/--data/--data-raw/--data-binary/--data-ascii/--data-urlencode) are not supported');
}

// must have a URL
if (curlObj.args.length > 1 && !curlObj.url) {
throw new Error('Only the URL can be provided without an option preceding it.' +
'All other inputs must be specified via options.');
' All other inputs must be specified via options.');
}
},

Expand Down Expand Up @@ -401,6 +401,28 @@ var program,
}
},

/**
* Transforms corresponding cURL in Windows CMD format to Bash compatible version,
* via unescaping escaped characters for Windows CMD.
*
* @param {String} curlString - curL string to be transformed into respectivve bash version
* @returns {String} - Transformed cURL in Bash format
*/
transformCmdToBash: function (curlString) {
/**
* three kinds of matching groups can be captured with following regexp.
* 1. Certain characters that can be escaped by ^ (caret). Namely ^,{,},[,],<,>,\,",|,&,\n(new line)
* These will be replaced with character itself resulting in removal of escape char (^)
* 2. ^%^ specifically will be replaced with % due to special escape rule
* 3. "" will be replaced with "
* (single quotations are escaped with double quotes when inside string that's wrapped in double quotes)
*
* Ref: https://ss64.com/nt/syntax-esc.html
* See detail regexp composition over here: https://regex101.com/r/Xbiqbq/1
*/
return curlString.replace(new RegExp(/\^(\^|{|}|\[|\]|<|>|\\|"|\||&|\n)|\^(%)\^|"(")/, 'g'), '$1$2$3');
},

/**
* Parses raw data and generates object from it by understanding content present in it
*
Expand Down Expand Up @@ -470,7 +492,26 @@ var program,
return parsedFormData;
},

convertCurlToRequest: function(curlString) {
/**
* Converts cURL string that's in windows cmd compatible format into collection request
*
* @param {String} curlString - Windows cmd compatible cURL string
* @returns {Object} Collection request JSON
*/
convertForCMDFormat: function (curlString) {
try {
const bashCurlString = this.transformCmdToBash(curlString),
request = this.convertCurlToRequest(bashCurlString, false);

request.description = 'Generated from a curl request: \n' + curlString.split('"').join('\\\"');
return request;
}
catch (error) {
throw e;
}
},

convertCurlToRequest: function(curlString, shouldRetry = true) {
try {
this.initialize();
this.requestUrl = '';
Expand Down Expand Up @@ -625,8 +666,16 @@ var program,
return request;
}
catch (e) {
if (shouldRetry) {
try {
// Retry conversion again by considering cURL to be in windows cmd compatible format
return this.convertForCMDFormat(curlString);
}
catch (error) {
// Retry error is not reported
webholik marked this conversation as resolved.
Show resolved Hide resolved
}
}
if (e.message === 'process.exit is not a function') {
// happened because of
e.message = 'Invalid format for cURL.';
}
return { error: e };
Expand Down
61 changes: 60 additions & 1 deletion test/conversion.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ describe('Curl converter should', function() {
}, function (err, result) {
expect(result.result).to.equal(false);
expect(result.reason).to.equal('Error while parsing cURL: Both (--head/-I) and' +
'(-d/--data/--data-raw/--data-binary/--data-ascii/--data-urlencode) are not supported');
' (-d/--data/--data-raw/--data-binary/--data-ascii/--data-urlencode) are not supported');
done();
});
});
Expand Down Expand Up @@ -885,6 +885,7 @@ describe('Curl converter should', function() {
});
});
});

it('in case where there is a invalid character at the end it should throw an error', function(done) {
convert({
type: 'string',
Expand All @@ -900,4 +901,62 @@ describe('Curl converter should', function() {
done();
});
});

describe('[Github #5182]: It should correctly import cURL commands compatible with Windows cmd', function() {

it('containing double quotes escaped with ^ (caret)', function(done) {
convert({
type: 'string',
data: 'curl "https://trello.com/1/cards" --data-binary ' +
'"^{^\\^"name^\\^":^\\^"hello world^\\^",^\\^"pos^\\^":65535,^\\^"closed^\\^":false,' +
'^\\^"idLabels^\\^":^[^],^\\^"idMembers^\\^":^[^],^\\^"dateLastActivity^\\^":1536871503239,' +
'^\\^"idBoard^\\^":^\\^"5a84a94fc77d9f99cf9ecd8a^\\^",^\\^"idList^\\^":^\\^"a^\\^",' +
'^\\^"token^\\^":^\\^"a/L8nmd9rC5gyBYaBx6RVXGjHuMIRfMQS4b3p3zIhKWin8ejxTzJ5E5ERACxT2IILp^\\^"^}" --compressed'
}, function (err, result) {
expect(result.result).to.equal(true);
expect(result.output.length).to.equal(1);
expect(result.output[0].type).to.equal('request');
expect(result.output[0].data.url).to.equal('https://trello.com/1/cards');
done();
});
});

it('containing double quotes escaped with " (double quotes)', function(done) {
convert({
type: 'string',
data: `curl "https://www.youtube.com/youtubei/v1/guide?key=321456467855697&prettyPrint=false" ^
-H "authority: www.youtube.com" ^
-H "sec-ch-ua: ^\\^"Not_A Brand^\\^";v=^\\^"99^\\^", ^\\^"Chromium^\\^";v=^\\^"109^\\^"" ^
-H "sec-ch-ua-arch: ^\\^"arm^\\^"" ^
-H "user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) (KHTML, like Gecko) Chrome/109.0.0.0" ^
-H "content-type: application/json" ^
--data-raw "^{^\\^"context^\\^":^{^\\^"client^\\^":^{^\\^"hl^\\^":^\\^"en^\\^"^}^},^\\^"state^\\^":true^}" ^
--compressed
`
}, function (err, result) {
expect(result.result).to.equal(true);
expect(result.output.length).to.equal(1);
expect(result.output[0].type).to.equal('request');
const headerArr = result.output[0].data.header;
expect(headerArr[0].key).to.equal('authority');
expect(headerArr[0].value).to.equal('www.youtube.com');
expect(headerArr[1].key).to.equal('sec-ch-ua');
expect(headerArr[1].value).to.equal(
'\"Not_A Brand\";v=\"99\", \"Chromium\";v=\"109\"');
expect(headerArr[2].key).to.equal('sec-ch-ua-arch');
expect(headerArr[2].value).to.equal('\"arm\"');
expect(headerArr[3].key).to.equal('user-agent');
expect(headerArr[3].value).to.equal(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) (KHTML, like Gecko) Chrome/109.0.0.0');
expect(headerArr[4].key).to.equal('content-type');
expect(headerArr[4].value).to.equal('application/json');
expect(result.output[0].data.url).to.equal(
'https://www.youtube.com/youtubei/v1/guide?key=321456467855697&prettyPrint=false');
expect(result.output[0].data.body.mode).to.equal('raw');
expect(result.output[0].data.body.raw).to.equal(
'{\"context\":{\"client\":{\"hl\":\"en\"}},\"state\":true}');
done();
});
});
});
});