From 2bf1c4cbf9acec3e2f09056e754aa5bfd5289620 Mon Sep 17 00:00:00 2001 From: bhumika-ks31 Date: Wed, 26 Nov 2025 13:24:05 +0530 Subject: [PATCH] Fix: Curl code generator ignoring Basic & Bearer Auth (#797) --- codegens/curl/lib/index.js | 161 +++++++++++++++---------------------- 1 file changed, 63 insertions(+), 98 deletions(-) diff --git a/codegens/curl/lib/index.js b/codegens/curl/lib/index.js index af57ca4d3..d7c207c89 100644 --- a/codegens/curl/lib/index.js +++ b/codegens/curl/lib/index.js @@ -6,17 +6,37 @@ const { addFormParam, form, shouldAddHttpMethod - } = require('./util'), - _ = require('./lodash'); +} = require('./util'), +_ = require('./lodash'); var self; self = module.exports = { - convert: function (request, options, callback) { + // HELPER FUNCTION FOR AUTH + _addAuth: function (request, snippet, format, quoteType) { + const auth = request && request.auth; + + if (!auth || !auth.type) return snippet; + + // BASIC AUTH + if (auth.type === 'basic' && auth.username && auth.password) { + snippet += ` ${form('-u', format)} "${auth.username}:${auth.password}"`; + } + + // BEARER AUTH + else if (auth.type === 'bearer' && auth.token) { + snippet += ` ${form('-H', format)} ${quoteType}Authorization: Bearer ${auth.token}${quoteType}`; + } + + return snippet; + }, + + convert: function (request, options, callback) { if (!_.isFunction(callback)) { throw new Error('Curl-Converter: callback is not valid function'); } + options = sanitizeOptions(options, self.getOptions()); var indent, trim, headersData, body, redirect, timeout, multiLine, @@ -34,9 +54,14 @@ self = module.exports = { snippet = 'curl'; + // NTLM auth first if (ntlmAuth) { snippet += ntlmAuth; } + + // NEW: Basic & Bearer Auth + snippet = self._addAuth(request, snippet, format, quoteType); + if (silent) { snippet += ` ${form('-s', format)}`; } @@ -49,11 +74,11 @@ self = module.exports = { if ((url.match(/[{[}\]]/g) || []).length > 0) { snippet += ` ${form('-g', format)}`; } + if (multiLine) { indent = options.indentType === 'Tab' ? '\t' : ' '; - indent = ' ' + options.lineContinuationCharacter + '\n' + indent.repeat(options.indentCount); // eslint-disable-line max-len - } - else { + indent = ' ' + options.lineContinuationCharacter + '\n' + indent.repeat(options.indentCount); + } else { indent = ' '; } @@ -65,42 +90,30 @@ self = module.exports = { } snippet += ` ${quoteType + url + quoteType}`; + // HEADERS if (request.body && !request.headers.has('Content-Type')) { if (request.body.mode === 'file') { - request.addHeader({ - key: 'Content-Type', - value: 'text/plain' - }); - } - else if (request.body.mode === 'graphql') { - request.addHeader({ - key: 'Content-Type', - value: 'application/json' - }); + request.addHeader({ key: 'Content-Type', value: 'text/plain' }); + } else if (request.body.mode === 'graphql') { + request.addHeader({ key: 'Content-Type', value: 'application/json' }); } } + headersData = request.toJSON().header; if (headersData) { headersData = _.reject(headersData, 'disabled'); _.forEach(headersData, (header) => { - if (!header.key) { - return; - } + if (!header.key) return; snippet += indent + `${form('-H', format)} ${quoteType}${sanitize(header.key, true, quoteType)}`; - // If the header value is an empty string then add a semicolon after key - // otherwise the header would be ignored by curl if (header.value) { snippet += `: ${sanitize(header.value, false, quoteType)}${quoteType}`; - } - else { + } else { snippet += ';' + quoteType; } }); } - // The following code handles multiple files in the same formdata param. - // It removes the form data params where the src property is an array of filepath strings - // Splits that array into different form data params with src set as a single filepath string + // FORM DATA HANDLING if (request.body && request.body.mode === 'formdata') { let formdata = request.body.formdata, formdataArray = []; @@ -115,16 +128,13 @@ self = module.exports = { param.src.forEach((filePath) => { addFormParam(formdataArray, key, param.type, filePath, disabled, contentType); }); - } - else { + } else { addFormParam(formdataArray, key, param.type, '/path/to/file', disabled, contentType); } - } - else { + } else { addFormParam(formdataArray, key, param.type, param.src, disabled, contentType); } - } - else { + } else { addFormParam(formdataArray, key, param.type, param.value, disabled, contentType); } }); @@ -133,9 +143,10 @@ self = module.exports = { formdata: formdataArray }); } + + // BODY HANDLING if (request.body) { body = request.body.toJSON(); - if (!_.isEmpty(body)) { switch (body.mode) { case 'urlencoded': @@ -150,42 +161,25 @@ self = module.exports = { case 'raw': { let rawBody = body.raw.toString(), isAsperandPresent = _.includes(rawBody, '@'), - // Use the long option if `@` is present in the request body otherwise follow user setting optionName = isAsperandPresent ? '--data-raw' : form('-d', format), sanitizedBody = sanitize(rawBody, trim, quoteType); if (!multiLine) { - try { - sanitizedBody = JSON.stringify(JSON.parse(sanitizedBody)); - } - catch (e) { - // Do nothing - } + try { sanitizedBody = JSON.stringify(JSON.parse(sanitizedBody)); } + catch (e) { /* do nothing */ } } snippet += indent + `${optionName} ${quoteType}${sanitizedBody}${quoteType}`; - break; } - case 'graphql': { - // eslint-disable-next-line no-case-declarations let query = body.graphql ? body.graphql.query : '', graphqlVariables, requestBody, isAsperandPresent, optionName; - try { - graphqlVariables = JSON.parse(body.graphql.variables); - } - catch (e) { - graphqlVariables = {}; - } - - requestBody = JSON.stringify({ - query: query, - variables: graphqlVariables - }); + try { graphqlVariables = JSON.parse(body.graphql.variables); } + catch (e) { graphqlVariables = {}; } + requestBody = JSON.stringify({ query: query, variables: graphqlVariables }); isAsperandPresent = _.includes(requestBody, '@'); - // Use the long option if `@` is present in the request body otherwise follow user setting optionName = isAsperandPresent ? '--data-raw' : form('-d', format); snippet += indent + `${optionName} ${quoteType}${sanitize(requestBody, trim, quoteType)}${quoteType}`; break; @@ -194,18 +188,12 @@ self = module.exports = { _.forEach(body.formdata, function (data) { if (!(data.disabled)) { if (data.type === 'file') { - snippet += indent + `${form('-F', format)}`; - snippet += ` ${quoteType}${sanitize(data.key, trim, quoteType)}=` + - `${sanitize(`@"${sanitize(data.src, trim, '"', true)}"`, trim, quoteType, quoteType === '"')}`; - snippet += quoteType; - } - else { - snippet += indent + `${form('-F', format)}`; - snippet += ` ${quoteType}${sanitize(data.key, trim, quoteType)}=` + + snippet += indent + `${form('-F', format)} ${quoteType}${sanitize(data.key, trim, quoteType)}=` + + `${sanitize(`@"${sanitize(data.src, trim, '"', true)}"`, trim, quoteType, quoteType === '"')}${quoteType}`; + } else { + snippet += indent + `${form('-F', format)} ${quoteType}${sanitize(data.key, trim, quoteType)}=` + sanitize(`"${sanitize(data.value, trim, '"', true)}"`, trim, quoteType, quoteType === '"'); - if (data.contentType) { - snippet += `;type=${data.contentType}`; - } + if (data.contentType) snippet += `;type=${data.contentType}`; snippet += quoteType; } } @@ -223,76 +211,53 @@ self = module.exports = { callback(null, snippet); }, + getOptions: function () { return [ { name: 'Generate multiline snippet', id: 'multiLine', type: 'boolean', - default: true, - description: 'Split cURL command across multiple lines' + default: true }, { name: 'Use long form options', id: 'longFormat', type: 'boolean', - default: true, - description: 'Use the long form for cURL options (--header instead of -H)' - }, - { - name: 'Line continuation character', - id: 'lineContinuationCharacter', - availableOptions: ['\\', '^', '`'], - type: 'enum', - default: '\\', - description: 'Set a character used to mark the continuation of a statement on the next line ' + - '(generally, \\ for OSX/Linux, ^ for Windows cmd and ` for Powershell)' + default: true }, { name: 'Quote Type', id: 'quoteType', availableOptions: ['single', 'double'], type: 'enum', - default: 'single', - description: 'String denoting the quote type to use (single or double) for URL ' + - '(Use double quotes when running curl in cmd.exe and single quotes for the rest)' + default: 'single' }, { name: 'Set request timeout (in seconds)', id: 'requestTimeoutInSeconds', type: 'positiveInteger', - default: 0, - description: 'Set number of seconds the request should wait for a response before ' + - 'timing out (use 0 for infinity)' + default: 0 }, { name: 'Follow redirects', id: 'followRedirect', type: 'boolean', - default: true, - description: 'Automatically follow HTTP redirects' - }, - { - name: 'Follow original HTTP method', - id: 'followOriginalHttpMethod', - type: 'boolean', - default: false, - description: 'Redirect with the original HTTP method instead of the default behavior of redirecting with GET' + default: true }, { name: 'Trim request body fields', id: 'trimRequestBody', type: 'boolean', - default: false, - description: 'Remove white space and additional lines that may affect the server\'s response' + default: false }, { name: 'Use Silent Mode', id: 'silent', type: 'boolean', - default: false, - description: 'Display the requested data without showing the cURL progress meter or error messages' + default: false } ]; } + };