diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f3982db4..e422c1ac0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## [Unreleased] +## [v1.9.0] - 2024-01-18 + +### Fixed + +- Fix for - [#10139](https://github.com/postmanlabs/postman-app-support/issues/10139) Modify Swift codegen to work with multipart/form-data format, used for video file upload + ## [v1.8.0] - 2023-06-27 - Fix for - [#10521](https://github.com/postmanlabs/postman-app-support/issues/10521) Add support for Dart Dio snippet generation @@ -140,7 +146,9 @@ v1.0.0 (May 29, 2020) - Add ES6 syntax support for NodeJS Request, NodeJS Native and NodeJS Unirest - Fix snippet generation for powershell and jquery, where form data params had no type field -[Unreleased]: https://github.com/postmanlabs/postman-code-generators/compare/v1.8.0...HEAD +[Unreleased]: https://github.com/postmanlabs/postman-code-generators/compare/v1.9.0...HEAD + +[v1.9.0]: https://github.com/postmanlabs/postman-code-generators/compare/v1.8.0...v1.9.0 [v1.8.0]: https://github.com/postmanlabs/postman-code-generators/compare/v1.7.2...v1.8.0 diff --git a/codegens/js-fetch/README.md b/codegens/js-fetch/README.md index 2d592ae1d..f338dfe8f 100644 --- a/codegens/js-fetch/README.md +++ b/codegens/js-fetch/README.md @@ -19,6 +19,7 @@ Convert function takes three parameters * `trimRequestBody` - Trim request body fields * `followRedirect` - Boolean denoting whether to redirect a request * `requestTimeout` - Integer denoting time after which the request will bail out in milli-seconds + * `asyncAwaitEnabled` : Boolean denoting whether to use async/await syntax * `callback` - callback function with first parameter as error and second parameter as string for code snippet diff --git a/codegens/js-fetch/lib/index.js b/codegens/js-fetch/lib/index.js index d93c8b385..701e22db7 100644 --- a/codegens/js-fetch/lib/index.js +++ b/codegens/js-fetch/lib/index.js @@ -24,7 +24,7 @@ function redirectMode (redirect) { * @param {boolean} trim trim body option */ function parseURLEncodedBody (body, trim) { - var bodySnippet = 'var urlencoded = new URLSearchParams();\n'; + var bodySnippet = 'const urlencoded = new URLSearchParams();\n'; _.forEach(body, function (data) { if (!data.disabled) { bodySnippet += `urlencoded.append("${sanitize(data.key, trim)}", "${sanitize(data.value, trim)}");\n`; @@ -40,7 +40,7 @@ function parseURLEncodedBody (body, trim) { * @param {boolean} trim trim body option */ function parseFormData (body, trim) { - var bodySnippet = 'var formdata = new FormData();\n'; + var bodySnippet = 'const formdata = new FormData();\n'; _.forEach(body, function (data) { if (!data.disabled) { if (data.type === 'file') { @@ -65,7 +65,7 @@ function parseFormData (body, trim) { * @param {String} indentString Indentation string */ function parseRawBody (body, trim, contentType, indentString) { - var bodySnippet = 'var raw = '; + var bodySnippet = 'const raw = '; // Match any application type whose underlying structure is json // For example application/vnd.api+json // All of them have +json as suffix @@ -101,7 +101,7 @@ function parseGraphQL (body, trim, indentString) { catch (e) { graphqlVariables = {}; } - bodySnippet = 'var graphql = JSON.stringify({\n'; + bodySnippet = 'const graphql = JSON.stringify({\n'; bodySnippet += `${indentString}query: "${sanitize(query, trim)}",\n`; bodySnippet += `${indentString}variables: ${JSON.stringify(graphqlVariables)}\n})`; return bodySnippet; @@ -113,7 +113,7 @@ function parseGraphQL (body, trim, indentString) { * parses binamry file data */ function parseFileData () { - var bodySnippet = 'var file = "";\n'; + var bodySnippet = 'const file = "";\n'; return bodySnippet; } @@ -154,7 +154,7 @@ function parseBody (body, trim, indentString, contentType) { function parseHeaders (headers) { var headerSnippet = ''; if (!_.isEmpty(headers)) { - headerSnippet = 'var myHeaders = new Headers();\n'; + headerSnippet = 'const myHeaders = new Headers();\n'; headers = _.reject(headers, 'disabled'); _.forEach(headers, function (header) { headerSnippet += `myHeaders.append("${sanitize(header.key, true)}", "${sanitize(header.value)}");\n`; @@ -209,6 +209,13 @@ function getOptions () { type: 'boolean', default: false, description: 'Remove white space and additional lines that may affect the server\'s response' + }, + { + name: 'Use async/await', + id: 'asyncAwaitEnabled', + type: 'boolean', + default: false, + description: 'Modifies code snippet to use async/await' } ]; } @@ -238,7 +245,6 @@ function convert (request, options, callback) { headerSnippet = '', bodySnippet = '', optionsSnippet = '', - timeoutSnippet = '', fetchSnippet = ''; indent = indent.repeat(options.indentCount); if (request.body && request.body.mode === 'graphql' && !request.headers.has('Content-Type')) { @@ -294,8 +300,12 @@ function convert (request, options, callback) { body = request.body && request.body.toJSON(); bodySnippet = parseBody(body, trim, indent, request.headers.get('Content-Type')); - optionsSnippet = `var requestOptions = {\n${indent}`; - optionsSnippet += `method: '${request.method}',\n${indent}`; + if (options.requestTimeout > 0) { + codeSnippet += 'const controller = new AbortController();\n'; + codeSnippet += `const timerId = setTimeout(() => controller.abort(), ${options.requestTimeout});\n`; + } + optionsSnippet = `const requestOptions = {\n${indent}`; + optionsSnippet += `method: "${request.method}",\n${indent}`; if (headerSnippet !== '') { optionsSnippet += `headers: myHeaders,\n${indent}`; codeSnippet += headerSnippet + '\n'; @@ -305,30 +315,39 @@ function convert (request, options, callback) { optionsSnippet += `body: ${body.mode},\n${indent}`; codeSnippet += bodySnippet + '\n'; } - optionsSnippet += `redirect: '${redirectMode(options.followRedirect)}'\n};\n`; + if (options.requestTimeout > 0) { + optionsSnippet += `signal: controller.signal,\n${indent}`; + } + optionsSnippet += `redirect: "${redirectMode(options.followRedirect)}"\n};\n`; codeSnippet += optionsSnippet + '\n'; - fetchSnippet = `fetch("${sanitize(request.url.toString())}", requestOptions)\n${indent}`; - fetchSnippet += `.then(response => response.text())\n${indent}`; - fetchSnippet += `.then(result => console.log(result))\n${indent}`; - fetchSnippet += '.catch(error => console.log(\'error\', error));'; - - if (options.requestTimeout > 0) { - timeoutSnippet = `var promise = Promise.race([\n${indent}`; - timeoutSnippet += `fetch('${request.url.toString()}', requestOptions)\n${indent}${indent}`; - timeoutSnippet += `.then(response => response.text()),\n${indent}`; - timeoutSnippet += `new Promise((resolve, reject) =>\n${indent}${indent}`; - timeoutSnippet += `setTimeout(() => reject(new Error('Timeout')), ${options.requestTimeout})\n${indent}`; - timeoutSnippet += ')\n]);\n\n'; - timeoutSnippet += 'promise.then(result => console.log(result)),\n'; - timeoutSnippet += 'promise.catch(error => console.log(error));'; - codeSnippet += timeoutSnippet; + if (options.asyncAwaitEnabled) { + fetchSnippet += `try {\n${indent}`; + fetchSnippet += `const response = await fetch("${sanitize(request.url.toString())}", requestOptions);\n${indent}`; + fetchSnippet += `const result = await response.text();\n${indent}`; + fetchSnippet += 'console.log(result)\n'; + fetchSnippet += `} catch (error) {\n${indent}`; + fetchSnippet += 'console.error(error);\n'; + if (options.requestTimeout > 0) { + fetchSnippet += `} finally {\n${indent}`; + fetchSnippet += 'clearTimeout(timerId);\n'; + } + fetchSnippet += '};'; } else { - codeSnippet += fetchSnippet; + fetchSnippet = `fetch("${sanitize(request.url.toString())}", requestOptions)\n${indent}`; + fetchSnippet += `.then((response) => response.text())\n${indent}`; + fetchSnippet += `.then((result) => console.log(result))\n${indent}`; + fetchSnippet += '.catch((error) => console.error(error))'; + if (options.requestTimeout > 0) { + fetchSnippet += `\n${indent}.finally(() => clearTimeout(timerId))`; + } + fetchSnippet += ';'; } + codeSnippet += fetchSnippet; + callback(null, codeSnippet); } diff --git a/codegens/js-fetch/test/unit/convert.test.js b/codegens/js-fetch/test/unit/convert.test.js index 23105ab1e..34b10e8f3 100644 --- a/codegens/js-fetch/test/unit/convert.test.js +++ b/codegens/js-fetch/test/unit/convert.test.js @@ -23,11 +23,10 @@ describe('js-fetch convert function for test collection', function () { expect.fail(null, null, error); return; } - expect(snippet).to.be.a('string'); snippetArray = snippet.split('\n'); for (var i = 0; i < snippetArray.length; i++) { - if (snippetArray[i] === 'var requestOptions = {') { line_no = i + 1; } + if (snippetArray[i] === 'const requestOptions = {') { line_no = i + 1; } } expect(snippetArray[line_no].charAt(0)).to.equal(' '); expect(snippetArray[line_no].charAt(1)).to.equal(' '); @@ -95,7 +94,7 @@ describe('js-fetch convert function for test collection', function () { return; } expect(snippet).to.be.a('string'); - expect(snippet).to.include('redirect: \'manual\''); + expect(snippet).to.include('redirect: "manual"'); }); }); @@ -111,7 +110,7 @@ describe('js-fetch convert function for test collection', function () { return; } expect(snippet).to.be.a('string'); - expect(snippet).to.include('redirect: \'follow\''); + expect(snippet).to.include('redirect: "follow"'); }); }); @@ -298,6 +297,62 @@ describe('js-fetch convert function for test collection', function () { expect(snippet).to.include('fetch("https://postman-echo.com/get?query1=b\'b&query2=c\\"c"'); }); }); + + it('should return snippet with promise based code when async_await is disabled', function () { + const request = new sdk.Request(mainCollection.item[0].request); + + convert(request, {}, function (error, snippet) { + if (error) { + expect.fail(null, null, error); + } + expect(snippet).to.be.a('string'); + expect(snippet).to.include('fetch('); + expect(snippet).to.include('.then((response) => '); + expect(snippet).to.include('.catch((error) => '); + }); + }); + + it('should return snippet with async/await based code when option is enabled', function () { + const request = new sdk.Request(mainCollection.item[0].request); + + convert(request, { asyncAwaitEnabled: true }, function (error, snippet) { + if (error) { + expect.fail(null, null, error); + } + expect(snippet).to.be.a('string'); + expect(snippet).to.include('const response = await fetch('); + expect(snippet).to.include('const result = await response.text()'); + expect(snippet).to.include('catch (error) {'); + }); + }); + + it('should return timeout snippet with promise based code when async_await is disabled', function () { + const request = new sdk.Request(mainCollection.item[0].request); + + convert(request, { requestTimeout: 3000 }, function (error, snippet) { + if (error) { + expect.fail(null, null, error); + } + expect(snippet).to.be.a('string'); + expect(snippet).to.include('const controller'); + expect(snippet).to.include('const timerId'); + expect(snippet).to.include('.finally(() => clearTimeout(timerId))'); + }); + }); + + it('should return timeout snippet with promise based code when async_await is enabled', function () { + const request = new sdk.Request(mainCollection.item[0].request); + + convert(request, { requestTimeout: 3000, asyncAwaitEnabled: true }, function (error, snippet) { + if (error) { + expect.fail(null, null, error); + } + expect(snippet).to.be.a('string'); + expect(snippet).to.include('const controller'); + expect(snippet).to.include('const timerId'); + expect(snippet).to.include('} finally {'); + }); + }); }); describe('getOptions function', function () { @@ -312,6 +367,7 @@ describe('js-fetch convert function for test collection', function () { expect(getOptions()[2]).to.have.property('id', 'requestTimeout'); expect(getOptions()[3]).to.have.property('id', 'followRedirect'); expect(getOptions()[4]).to.have.property('id', 'trimRequestBody'); + expect(getOptions()[5]).to.have.property('id', 'asyncAwaitEnabled'); }); }); diff --git a/codegens/libcurl/lib/index.js b/codegens/libcurl/lib/index.js index 3e16cf630..d432f98d3 100644 --- a/codegens/libcurl/lib/index.js +++ b/codegens/libcurl/lib/index.js @@ -214,6 +214,9 @@ self = module.exports = { if (body.mode === 'formdata' && options.useMimeType) { snippet += indentString + 'curl_mime_free(mime);\n'; } + if (headersData) { + snippet += indentString + 'curl_slist_free_all(headers);\n'; + } snippet += '}\n'; snippet += 'curl_easy_cleanup(curl);\n'; (options.includeBoilerplate) && diff --git a/codegens/libcurl/test/unit/convert.test.js b/codegens/libcurl/test/unit/convert.test.js index 4f81e14d9..5ff1e9630 100644 --- a/codegens/libcurl/test/unit/convert.test.js +++ b/codegens/libcurl/test/unit/convert.test.js @@ -145,6 +145,38 @@ describe('libcurl convert function', function () { expect(snippet).to.include('curl_mime_name(part, "invalid src");'); }); }); + + it('should free up headers list after request is sent', function () { + var request = new sdk.Request({ + 'method': 'GET', + 'header': [ + { + 'key': 'Accept', + 'value': 'application/json' + }, + { + 'key': 'Content-Type', + 'value': 'application/json' + } + ], + 'url': { + 'raw': 'https://google.com', + 'protocol': 'https', + 'host': [ + 'google', + 'com' + ] + } + }); + convert(request, {}, function (error, snippet) { + if (error) { + expect.fail(null, null, error); + } + expect(snippet).to.be.a('string'); + expect(snippet).to.include('curl_slist_free_all(headers)'); + }); + }); + }); describe('getOptions function', function () { diff --git a/codegens/swift/lib/swift.js b/codegens/swift/lib/swift.js index 0f3cf5320..a27f2fd8d 100644 --- a/codegens/swift/lib/swift.js +++ b/codegens/swift/lib/swift.js @@ -111,29 +111,34 @@ function parseFormData (body, mode, trim, indent) { parameters = '[\n' + _.join(parameters, ',\n') + ']'; bodySnippet = `let parameters = ${parameters} as [[String: Any]]\n\n`; bodySnippet += 'let boundary = "Boundary-\\(UUID().uuidString)"\n'; - bodySnippet += 'var body = ""\nvar error: Error? = nil\n'; + bodySnippet += 'var body = Data()\nvar error: Error? = nil\n'; bodySnippet += 'for param in parameters {\n'; bodySnippet += `${indent}if param["disabled"] != nil { continue }\n`; bodySnippet += `${indent}let paramName = param["key"]!\n`; - bodySnippet += `${indent}body += "--\\(boundary)\\r\\n"\n`; + bodySnippet += `${indent}body += Data("--\\(boundary)\\r\\n".utf8)\n`; // eslint-disable-next-line no-useless-escape - bodySnippet += `${indent}body += "Content-Disposition:form-data; name=\\"\\(paramName)\\"\"\n`; + bodySnippet += `${indent}body += Data("Content-Disposition:form-data; name=\\"\\(paramName)\\"\".utf8)\n`; bodySnippet += `${indent}if param["contentType"] != nil {\n`; - bodySnippet += `${indent.repeat(2)}body += "\\r\\nContent-Type: \\(param["contentType"] as! String)"\n`; + bodySnippet += `${indent.repeat(2)}body += Data("\\r\\nContent-Type: \\(param["contentType"] as! String)".utf8)\n`; bodySnippet += `${indent}}\n`; bodySnippet += `${indent}let paramType = param["type"] as! String\n`; bodySnippet += `${indent}if paramType == "text" {\n`; bodySnippet += `${indent.repeat(2)}let paramValue = param["value"] as! String\n`; - bodySnippet += `${indent.repeat(2)}body += "\\r\\n\\r\\n\\(paramValue)\\r\\n"\n`; + bodySnippet += `${indent.repeat(2)}body += Data("\\r\\n\\r\\n\\(paramValue)\\r\\n".utf8)\n`; bodySnippet += `${indent}} else {\n`; bodySnippet += `${indent.repeat(2)}let paramSrc = param["src"] as! String\n`; - bodySnippet += `${indent.repeat(2)}let fileData = try NSData(contentsOfFile: paramSrc, options: []) as Data\n`; - bodySnippet += `${indent.repeat(2)}let fileContent = String(data: fileData, encoding: .utf8)!\n`; - bodySnippet += `${indent.repeat(2)}body += "; filename=\\"\\(paramSrc)\\"\\r\\n"\n`; - bodySnippet += `${indent.repeat(2)} + "Content-Type: \\"content-type header\\"\\r\\n\\r\\n`; - bodySnippet += '\\(fileContent)\\r\\n"\n'; - bodySnippet += `${indent}}\n}\nbody += "--\\(boundary)--\\r\\n";\n`; - bodySnippet += 'let postData = body.data(using: .utf8)'; + bodySnippet += `${indent.repeat(2)}let fileURL = URL(fileURLWithPath: paramSrc)\n`; + bodySnippet += `${indent.repeat(2)}if let fileContent = try? Data(contentsOf: fileURL) {\n`; + bodySnippet += `${indent.repeat(3)}body += Data("; filename=\\"\\(paramSrc)\\"\\r\\n".utf8)\n`; + bodySnippet += `${indent.repeat(3)}body += Data("Content-Type: \\"content-type header\\"\\r\\n".utf8)\n`; + bodySnippet += `${indent.repeat(3)}body += Data("\\r\\n".utf8)\n`; + bodySnippet += `${indent.repeat(3)}body += fileContent\n`; + bodySnippet += `${indent.repeat(3)}body += Data("\\r\\n".utf8)\n`; + bodySnippet += `${indent.repeat(2)}}\n`; + bodySnippet += `${indent}}\n`; + bodySnippet += '}\n'; + bodySnippet += 'body += Data("--\\(boundary)--\\r\\n".utf8);\n'; + bodySnippet += 'let postData = body\n'; return bodySnippet; } diff --git a/codegens/swift/test/unit/convert.test.js b/codegens/swift/test/unit/convert.test.js index ba8997124..5be4966fe 100644 --- a/codegens/swift/test/unit/convert.test.js +++ b/codegens/swift/test/unit/convert.test.js @@ -62,7 +62,7 @@ describe('Swift Converter', function () { } expect(snippet).to.be.a('string'); expect(snippet).to.contain('if param["contentType"] != nil {'); - expect(snippet).to.contain('body += "\\r\\nContent-Type: \\(param["contentType"] as! String)"'); + expect(snippet).to.contain('body += Data("\\r\\nContent-Type: \\(param["contentType"] as! String)".utf8)'); }); }); diff --git a/package-lock.json b/package-lock.json index 93339fa6c..cda3db0e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "postman-code-generators", - "version": "1.8.0", + "version": "1.9.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 786c599ab..09792cc09 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "postman-code-generators", - "version": "1.8.0", + "version": "1.9.0", "description": "Generates code snippets for a postman collection", "main": "index.js", "directories": { diff --git a/test/codegen/newman/fixtures/basicCollection.json b/test/codegen/newman/fixtures/basicCollection.json index d0c79aca7..43c61e004 100644 --- a/test/codegen/newman/fixtures/basicCollection.json +++ b/test/codegen/newman/fixtures/basicCollection.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "f52ee07d-6345-4220-89af-e6696b3c0122", + "_postman_id": "b303fb8b-9b21-4429-b00f-33b6a7efa186", "name": "Basic Collection", "description": "This collection contains requests that will be used to test validity of plugin created to convert postman request into code snippet of particular language.", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" @@ -12,7 +12,6 @@ { "listen": "test", "script": { - "id": "34edbfa7-7d32-42d6-8397-af2378c3aaa4", "exec": [ "" ], @@ -53,7 +52,6 @@ }, { "name": "Request Headers", - "event": [], "request": { "method": "GET", "header": [ @@ -95,7 +93,6 @@ { "listen": "test", "script": { - "id": "e150d55b-0273-430a-9e1d-11969b433734", "exec": [ "" ], @@ -141,7 +138,6 @@ { "listen": "test", "script": { - "id": "1bfe1fc3-c244-4a42-83c5-1a0d94d56ffd", "exec": [ "" ], @@ -188,7 +184,6 @@ { "listen": "test", "script": { - "id": "a3ddecd1-e89d-426d-995c-0d6a678caa91", "exec": [ "var responseJSON;", "", @@ -216,8 +211,7 @@ "header": [ { "key": "Content-Type", - "value": "text/plain", - "disabled": false + "value": "text/plain" } ], "body": { @@ -245,7 +239,6 @@ { "listen": "test", "script": { - "id": "e926912d-1c99-4c54-9b53-91c8f63acef0", "exec": [ "" ], @@ -312,7 +305,6 @@ { "listen": "test", "script": { - "id": "d211bdad-60b3-4cd6-869f-853377bf03ef", "exec": [ "" ], @@ -353,7 +345,6 @@ { "listen": "test", "script": { - "id": "532fef57-48fd-4ffe-ac7e-f5a7e32facc2", "exec": [ "" ], @@ -394,7 +385,6 @@ { "listen": "test", "script": { - "id": "8bbbbc5b-2983-4979-8347-3ced95a69f7e", "exec": [ "" ], @@ -435,7 +425,6 @@ { "listen": "test", "script": { - "id": "48da0505-470f-4cf3-bb77-30665415af60", "exec": [ "" ], @@ -618,7 +607,6 @@ { "listen": "test", "script": { - "type": "text/javascript", "exec": [ "var responseJSON;", "", @@ -634,28 +622,23 @@ "", "tests['response has PUT data'] = _.has(responseJSON, 'data');", "tests['response matches the data sent in request'] = (responseJSON.data && responseJSON.data.length === 256);" - ] + ], + "type": "text/javascript" } } ], "request": { "method": "DELETE", - "header": [ - { - "key": "Content-Type", - "value": "text/plain" - } - ], - "body": {}, + "header": [], "url": { - "raw": "https://mockbin.org/request", + "raw": "https://postman-echo.com/delete", "protocol": "https", "host": [ - "mockbin", - "org" + "postman-echo", + "com" ], "path": [ - "request" + "delete" ] }, "description": "The HTTP `DELETE` method is used to delete resources on a server. The exact\nuse of `DELETE` requests depends on the server implementation. In general, \n`DELETE` requests support both, Query String parameters as well as a Request \nBody.\n\nThis endpoint accepts an HTTP `DELETE` request and provides debug information\nsuch as the HTTP headers, Query String arguments, and the Request Body." @@ -667,7 +650,6 @@ { "listen": "prerequest", "script": { - "id": "e80b6162-6c90-4150-bfa1-7f42f11c8f64", "type": "text/javascript", "exec": [ "" @@ -677,7 +659,6 @@ { "listen": "test", "script": { - "id": "538efa04-97ce-456c-a5a1-772c466591d5", "type": "text/javascript", "exec": [ "" @@ -685,4 +666,4 @@ } } ] -} +} \ No newline at end of file diff --git a/test/codegen/newman/fixtures/redirectCollection.json b/test/codegen/newman/fixtures/redirectCollection.json index 5fb851c47..15a4c15ba 100644 --- a/test/codegen/newman/fixtures/redirectCollection.json +++ b/test/codegen/newman/fixtures/redirectCollection.json @@ -1,31 +1,31 @@ { "info": { - "_postman_id": "3ef1c00f-c58f-4604-8419-7a4931958235", + "_postman_id": "17d62db7-ca12-4298-8782-1d6f018c7be2", "name": "Redirect test", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, "item": [ { "name": "Follow Redirects", + "protocolProfileBehavior": { + "followRedirects": true + }, "request": { "method": "GET", "header": [], "url": { - "raw": "https://mockbin.org/redirect/302/1/?to=https://postman-echo.com/get", + "raw": "https://httpbin.org/redirect-to?url=https://postman-echo.com/get", "protocol": "https", "host": [ - "mockbin", + "httpbin", "org" ], "path": [ - "redirect", - "302", - "1", - "" + "redirect-to" ], "query": [ { - "key": "to", + "key": "url", "value": "https://postman-echo.com/get" } ] @@ -33,6 +33,5 @@ }, "response": [] } - ], - "protocolProfileBehavior": {} + ] } \ No newline at end of file