Skip to content

Commit 190cbe4

Browse files
committed
Implemented json editor for headers and curl import funtionality
1 parent 88801b9 commit 190cbe4

File tree

2 files changed

+351
-66
lines changed

2 files changed

+351
-66
lines changed

src/utils/curlParser.js

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
const optionsRegex = /(--[a-zA-Z\-]+ '.*?')|(--[a-zA-Z\-]+)|(-[a-zA-Z\-]+? '.+?')|('?[a-z]+:\/\/.*?'+?)|("?[a-z]+:\/\/.*?"+?)/g; // eslint-disable-line
2+
const urlRegex = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/; // eslint-disable-line
3+
4+
const contentTypeHeader = 'content-type';
5+
const jsonMimeType = 'application/json';
6+
7+
const isMatchingOption = (headers, str) => {
8+
for (let i = 0; i < headers.length; i += 1) {
9+
if (str.startsWith(headers[i])) {
10+
return true;
11+
}
12+
}
13+
return false;
14+
};
15+
16+
const isAHeaderOption = str => isMatchingOption(['-H ', '--headers ', '--header '], str);
17+
const isDataOption = str => isMatchingOption(['--data ', '--data-ascii ', '-d ', '--data-raw ', '--data-urlencode ', '--data-binary '], str);
18+
19+
const removeLeadingTrailingQuotes = (str) => {
20+
const quotes = ['\'', '"'];
21+
let newStr = str.trim();
22+
if (quotes.includes(newStr[0])) {
23+
newStr = newStr.substr(1, newStr.length - 1)
24+
}
25+
if (quotes.includes(newStr[newStr.length - 1])) {
26+
newStr = newStr.substr(0, newStr.length - 1)
27+
}
28+
return newStr;
29+
};
30+
31+
const subStrFrom = (val, startFromVal) => {
32+
const dataPosition = val.indexOf(startFromVal);
33+
return val.substr(dataPosition);
34+
};
35+
36+
const isJsonRequest = parsedCommand => (parsedCommand.headers[contentTypeHeader] &&
37+
parsedCommand.headers[contentTypeHeader].indexOf(jsonMimeType) !== -1);
38+
39+
const parseBodyByContentType = (parsedCommand) => {
40+
const { body, headers } = parsedCommand
41+
// if (body && isJsonRequest(parsedCommand)) {
42+
if (body) {
43+
try {
44+
const cleanedBodyData = body.replace('\\"', '"').replace("\\'", "'");
45+
return JSON.parse(cleanedBodyData);
46+
} catch (ex) {
47+
// ignore json conversion error..
48+
console.log('Cannot parse JSON Data ' + ex.message); // eslint-disable-line
49+
}
50+
}
51+
return body;
52+
};
53+
54+
const parseOptionValue = (val) => {
55+
const headerSplit = subStrFrom(val, ' ').split(':');
56+
return {
57+
key: removeLeadingTrailingQuotes(headerSplit[0]).trim(),
58+
value: removeLeadingTrailingQuotes(headerSplit[1]).trim()
59+
};
60+
};
61+
62+
const parseQueryStrings = (url) => {
63+
const paramPosition = url.indexOf('?');
64+
const queryStrings = {};
65+
if (paramPosition !== -1) {
66+
// const splitUrl = parsedCommand.url.substr(0, paramPosition);
67+
const paramsString = url.substr(paramPosition + 1);
68+
const params = paramsString.split('&') || [];
69+
70+
params.forEach((param) => {
71+
const splitParam = param.split('='); // eslint-disable-line
72+
queryStrings[splitParam[0]] = splitParam[1]; // eslint-disable-line
73+
});
74+
}
75+
return queryStrings;
76+
};
77+
78+
const parseUrlOption = (val) => {
79+
const urlMatches = val.match(urlRegex) || [];
80+
if (urlMatches.length) {
81+
const url = urlMatches[0]; // eslint-disable-line
82+
return {
83+
url,
84+
queryStrings: parseQueryStrings(url),
85+
};
86+
}
87+
return { url: '', queryStrings: {} };
88+
};
89+
90+
const parseBody = val => removeLeadingTrailingQuotes(subStrFrom(val, ' '));
91+
92+
const isACurlCommand = val => val.trim().startsWith('curl ');
93+
const isAUrlOption = (val) => {
94+
const matches = val.match(urlRegex) || [];
95+
return !!matches.length;
96+
};
97+
98+
/*
99+
* Parse cUrl command to a JSON structure
100+
* params:
101+
* command - cUrl command as a string.
102+
* return JSON object
103+
*/
104+
export function parse(command) {
105+
if (!command) { return ''; }
106+
107+
const parsedCommand = {
108+
url: '',
109+
};
110+
111+
// quit if the command does not starts with curl
112+
if (isACurlCommand(command)) {
113+
// let cleanCommand = command.replace('\\\\n', '');
114+
let cleanCommand = command;
115+
cleanCommand = cleanCommand.replace(/(\\\r\n|\\\n|\\\r)/gm," ");
116+
cleanCommand = cleanCommand.replace(/(\r\n|\n|\r)/gm," ");
117+
118+
const matches = cleanCommand.match(optionsRegex);
119+
matches.forEach((val) => {
120+
// const option = removeLeadingTrailingQuotes(val);
121+
const option = val;
122+
if (isAUrlOption(option)) {
123+
const { url, queryStrings } = parseUrlOption(option);
124+
parsedCommand.url = url;
125+
parsedCommand.queryStrings = queryStrings;
126+
} else if (isAHeaderOption(option)) {
127+
const { key, value } = parseOptionValue(option);
128+
parsedCommand.headers = parsedCommand.headers || {};
129+
parsedCommand.headers[key] = value;
130+
} else if (isDataOption(option)) {
131+
parsedCommand.body = parseBody(option);
132+
} else {
133+
console.log(`Skipped Header ${val}`); // eslint-disable-line
134+
}
135+
}); // parse over matches ends
136+
137+
// should be checked after all the options are analyzed
138+
// so that we guarentee that we have content-type header
139+
parsedCommand.body = parseBodyByContentType(parsedCommand);
140+
}
141+
return parsedCommand;
142+
}
143+
144+
export default parse;

0 commit comments

Comments
 (0)