index.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. "use strict";
  2. var _ = require('../../lodash'), sanitize = require('./util').sanitize, sanitizeMultiline = require('./util').sanitizeMultiline, sanitizeOptions = require('./util').sanitizeOptions, addFormParam = require('./util').addFormParam, isFile = false, self;
  3. /**
  4. * Parses Raw data to fetch syntax
  5. *
  6. * @param {Object} body Raw body data
  7. * @param {boolean} trim trim body option
  8. */
  9. function parseRawBody(body, trim) {
  10. var bodySnippet;
  11. bodySnippet = `payload := strings.NewReader(\`${sanitizeMultiline(body.toString(), trim)}\`)`;
  12. return bodySnippet;
  13. }
  14. /**
  15. * Parses graphql data to golang syntax
  16. *
  17. * @param {Object} body Raw body data
  18. * @param {boolean} trim trim body option
  19. */
  20. function parseGraphQL(body, trim) {
  21. let query = body.query, graphqlVariables, bodySnippet;
  22. try {
  23. graphqlVariables = JSON.parse(body.variables);
  24. }
  25. catch (e) {
  26. graphqlVariables = {};
  27. }
  28. bodySnippet = `payload := strings.NewReader("${sanitize(JSON.stringify({
  29. query: query,
  30. variables: graphqlVariables
  31. }), trim)}")`;
  32. return bodySnippet;
  33. }
  34. /**
  35. * Parses URLEncoded body from request to fetch syntax
  36. *
  37. * @param {Object} body URLEncoded Body
  38. * @param {boolean} trim trim body option
  39. */
  40. function parseURLEncodedBody(body, trim) {
  41. var payload, bodySnippet;
  42. payload = _.reduce(body, function (accumulator, data) {
  43. if (!data.disabled) {
  44. accumulator.push(`${encodeURIComponent(data.key, trim)}=${encodeURIComponent(data.value, trim)}`);
  45. }
  46. return accumulator;
  47. }, []).join('&');
  48. bodySnippet = `payload := strings.NewReader("${payload}")`;
  49. return bodySnippet;
  50. }
  51. /**
  52. * Parses formData body from request to fetch syntax
  53. *
  54. * @param {Object} body formData Body
  55. * @param {boolean} trim trim body option
  56. * @param {string} indent indent string
  57. */
  58. function parseFormData(body, trim, indent) {
  59. var bodySnippet = `payload := &bytes.Buffer{}\n${indent}writer := multipart.NewWriter(payload)\n`;
  60. _.forEach(body, function (data, index) {
  61. if (!data.disabled) {
  62. if (data.type === 'file') {
  63. isFile = true;
  64. bodySnippet += `${indent}file, errFile${index + 1} := os.Open("${data.src}")\n`;
  65. bodySnippet += `${indent}defer file.Close()\n`;
  66. bodySnippet += `${indent}part${index + 1},
  67. errFile${index + 1} := writer.CreateFormFile("${sanitize(data.key, trim)}",` +
  68. `filepath.Base("${data.src}"))\n`;
  69. bodySnippet += `${indent}_, errFile${index + 1} = io.Copy(part${index + 1}, file)\n`;
  70. bodySnippet += `${indent}if errFile${index + 1} != nil {` +
  71. `\n${indent.repeat(2)}fmt.Println(errFile${index + 1})\n` +
  72. `${indent.repeat(2)}return\n${indent}}\n`;
  73. }
  74. else if (data.contentType) {
  75. bodySnippet += `\n${indent}mimeHeader${index + 1} := make(map[string][]string)\n`;
  76. bodySnippet += `${indent}mimeHeader${index + 1}["Content-Disposition"] = `;
  77. bodySnippet += `append(mimeHeader${index + 1}["Content-Disposition"], "form-data; `;
  78. bodySnippet += `name=\\"${sanitize(data.key, trim)}\\"")\n`;
  79. bodySnippet += `${indent}mimeHeader${index + 1}["Content-Type"] = append(`;
  80. bodySnippet += `mimeHeader${index + 1}["Content-Type"], "${data.contentType}")\n`;
  81. bodySnippet += `${indent}fieldWriter${index + 1}, _ := writer.CreatePart(mimeHeader${index + 1})\n`;
  82. bodySnippet += `${indent}fieldWriter${index + 1}.Write([]byte("${sanitize(data.value, trim)}"))\n\n`;
  83. }
  84. else {
  85. bodySnippet += `${indent}_ = writer.WriteField("${sanitize(data.key, trim)}",`;
  86. bodySnippet += ` "${sanitize(data.value, trim)}")\n`;
  87. }
  88. }
  89. });
  90. bodySnippet += `${indent}err := writer.Close()\n${indent}if err != nil ` +
  91. `{\n${indent.repeat(2)}fmt.Println(err)\n` +
  92. `${indent.repeat(2)}return\n${indent}}\n`;
  93. return bodySnippet;
  94. }
  95. /**
  96. * Parses file body from the Request
  97. *
  98. */
  99. function parseFile() {
  100. // var bodySnippet = `payload := &bytes.Buffer{}\n${indent}writer := multipart.NewWriter(payload)\n`;
  101. // isFile = true;
  102. // bodySnippet += `${indent}// add your file name in the next statement in place of path\n`;
  103. // bodySnippet += `${indent}file, err := os.Open(path)\n`;
  104. // bodySnippet += `${indent}defer file.Close()\n`;
  105. // bodySnippet += `${indent}part, err := writer.CreateFormFile("file", filepath.Base(path))\n`;
  106. // bodySnippet += `${indent}_, err := io.Copy(part, file)\n`;
  107. // bodySnippet += `${indent}err := writer.Close()\n${indent}if err != nil {${indent}fmt.Println(err)}\n`;
  108. var bodySnippet = 'payload := strings.NewReader("<file contents here>")\n';
  109. return bodySnippet;
  110. }
  111. /**
  112. * Parses Body from the Request
  113. *
  114. * @param {Object} body body object from request.
  115. * @param {boolean} trim trim body option
  116. * @param {string} indent indent string
  117. */
  118. function parseBody(body, trim, indent) {
  119. if (!_.isEmpty(body)) {
  120. switch (body.mode) {
  121. case 'urlencoded':
  122. return parseURLEncodedBody(body.urlencoded, trim);
  123. case 'raw':
  124. return parseRawBody(body.raw, trim);
  125. case 'graphql':
  126. return parseGraphQL(body.graphql, trim);
  127. case 'formdata':
  128. return parseFormData(body.formdata, trim, indent);
  129. case 'file':
  130. return parseFile(body.file, trim, indent);
  131. default:
  132. return '';
  133. }
  134. }
  135. return '';
  136. }
  137. /**
  138. * Parses headers from the request.
  139. *
  140. * @param {Object} headers headers from the request.
  141. * @param {string} indent indent string
  142. */
  143. function parseHeaders(headers, indent) {
  144. var headerSnippet = '';
  145. if (!_.isEmpty(headers)) {
  146. headers = _.reject(headers, 'disabled');
  147. _.forEach(headers, function (header) {
  148. headerSnippet += `${indent}req.Header.Add("${sanitize(header.key, true)}", "${sanitize(header.value)}")\n`;
  149. });
  150. }
  151. return headerSnippet;
  152. }
  153. self = module.exports = {
  154. convert: function (request, options, callback) {
  155. if (!_.isFunction(callback)) {
  156. throw new Error('GoLang-Converter: callback is not valid function');
  157. }
  158. options = sanitizeOptions(options, self.getOptions());
  159. var codeSnippet, indent, trim, timeout, followRedirect, bodySnippet = '', responseSnippet = '', headerSnippet = '';
  160. indent = options.indentType === 'Tab' ? '\t' : ' ';
  161. indent = indent.repeat(options.indentCount);
  162. timeout = options.requestTimeout;
  163. followRedirect = options.followRedirect;
  164. trim = options.trimRequestBody;
  165. // The following code handles multiple files in the same formdata param.
  166. // It removes the form data params where the src property is an array of filepath strings
  167. // Splits that array into different form data params with src set as a single filepath string
  168. if (request.body && request.body.mode === 'formdata') {
  169. let formdata = request.body.formdata, formdataArray = [];
  170. formdata.members.forEach((param) => {
  171. let key = param.key, type = param.type, disabled = param.disabled, contentType = param.contentType;
  172. if (type === 'file') {
  173. if (typeof param.src !== 'string') {
  174. if (Array.isArray(param.src) && param.src.length) {
  175. param.src.forEach((filePath) => {
  176. addFormParam(formdataArray, key, param.type, filePath, disabled, contentType);
  177. });
  178. }
  179. else {
  180. addFormParam(formdataArray, key, param.type, '/path/to/file', disabled, contentType);
  181. }
  182. }
  183. else {
  184. addFormParam(formdataArray, key, param.type, param.src, disabled, contentType);
  185. }
  186. }
  187. else {
  188. addFormParam(formdataArray, key, param.type, param.value, disabled, contentType);
  189. }
  190. });
  191. request.body.update({
  192. mode: 'formdata',
  193. formdata: formdataArray
  194. });
  195. }
  196. if (request.body) {
  197. bodySnippet = parseBody(request.body.toJSON(), trim, indent);
  198. }
  199. codeSnippet = 'package main\n\n';
  200. codeSnippet += `import (\n${indent}"fmt"\n`;
  201. if (timeout > 0) {
  202. codeSnippet += `${indent}"time"\n`;
  203. }
  204. if (request.body && request.body.toJSON().mode === 'formdata') {
  205. codeSnippet += `${indent}"bytes"\n${indent}"mime/multipart"\n`;
  206. }
  207. else if (bodySnippet !== '') {
  208. codeSnippet += `${indent}"strings"\n`;
  209. }
  210. if (isFile) {
  211. codeSnippet += `${indent}"os"\n${indent}"path/filepath"\n`;
  212. codeSnippet += `${indent}"io"\n`;
  213. // Setting isFile as false for further calls to this function
  214. isFile = false;
  215. }
  216. codeSnippet += `${indent}"net/http"\n${indent}"io/ioutil"\n)\n\n`;
  217. codeSnippet += `func main() {\n${indent}url := "${encodeURI(request.url.toString())}"\n`;
  218. codeSnippet += `${indent}method := "${request.method}"\n\n`;
  219. if (bodySnippet !== '') {
  220. codeSnippet += indent + bodySnippet + '\n\n';
  221. }
  222. if (timeout > 0) {
  223. codeSnippet += `${indent}timeout := time.Duration(${timeout / 1000} * time.Second)\n`;
  224. }
  225. codeSnippet += indent + 'client := &http.Client {\n';
  226. if (!followRedirect) {
  227. codeSnippet += indent.repeat(2) + 'CheckRedirect: func(req *http.Request, via []*http.Request) ';
  228. codeSnippet += 'error {\n';
  229. codeSnippet += `${indent.repeat(3)}return http.ErrUseLastResponse\n${indent.repeat(2)}},\n`;
  230. }
  231. if (timeout > 0) {
  232. codeSnippet += indent.repeat(2) + 'Timeout: timeout,\n';
  233. }
  234. codeSnippet += indent + '}\n';
  235. if (bodySnippet !== '') {
  236. codeSnippet += `${indent}req, err := http.NewRequest(method, url, payload)\n\n`;
  237. }
  238. else {
  239. codeSnippet += `${indent}req, err := http.NewRequest(method, url, nil)\n\n`;
  240. }
  241. codeSnippet += `${indent}if err != nil {\n${indent.repeat(2)}fmt.Println(err)\n`;
  242. codeSnippet += `${indent.repeat(2)}return\n${indent}}\n`;
  243. if (request.body && !request.headers.has('Content-Type')) {
  244. if (request.body.mode === 'file') {
  245. request.addHeader({
  246. key: 'Content-Type',
  247. value: 'text/plain'
  248. });
  249. }
  250. else if (request.body.mode === 'graphql') {
  251. request.addHeader({
  252. key: 'Content-Type',
  253. value: 'application/json'
  254. });
  255. }
  256. }
  257. headerSnippet = parseHeaders(request.toJSON().header, indent);
  258. if (headerSnippet !== '') {
  259. codeSnippet += headerSnippet + '\n';
  260. }
  261. if (request.body && (request.body.toJSON().mode === 'formdata')) {
  262. codeSnippet += `${indent}req.Header.Set("Content-Type", writer.FormDataContentType())\n`;
  263. }
  264. responseSnippet = `${indent}res, err := client.Do(req)\n`;
  265. responseSnippet += `${indent}if err != nil {\n${indent.repeat(2)}fmt.Println(err)\n`;
  266. responseSnippet += `${indent.repeat(2)}return\n${indent}}\n`;
  267. responseSnippet += `${indent}defer res.Body.Close()\n\n${indent}body, err := ioutil.ReadAll(res.Body)\n`;
  268. responseSnippet += `${indent}if err != nil {\n${indent.repeat(2)}fmt.Println(err)\n`;
  269. responseSnippet += `${indent.repeat(2)}return\n${indent}}\n`;
  270. responseSnippet += `${indent}fmt.Println(string(body))\n}`;
  271. codeSnippet += responseSnippet;
  272. callback(null, codeSnippet);
  273. },
  274. getOptions: function () {
  275. return [{
  276. name: 'Set indentation count',
  277. id: 'indentCount',
  278. type: 'positiveInteger',
  279. default: 2,
  280. description: 'Set the number of indentation characters to add per code level'
  281. },
  282. {
  283. name: 'Set indentation type',
  284. id: 'indentType',
  285. type: 'enum',
  286. availableOptions: ['Tab', 'Space'],
  287. default: 'Space',
  288. description: 'Select the character used to indent lines of code'
  289. },
  290. {
  291. name: 'Set request timeout',
  292. id: 'requestTimeout',
  293. type: 'positiveInteger',
  294. default: 0,
  295. description: 'Set number of milliseconds the request should wait for a ' +
  296. 'response before timing out (use 0 for infinity)'
  297. },
  298. {
  299. name: 'Follow redirects',
  300. id: 'followRedirect',
  301. type: 'boolean',
  302. default: true,
  303. description: 'Automatically follow HTTP redirects'
  304. },
  305. {
  306. name: 'Trim request body fields',
  307. id: 'trimRequestBody',
  308. type: 'boolean',
  309. default: false,
  310. description: 'Remove white space and additional lines that may affect the server\'s response'
  311. }];
  312. }
  313. };