From d6204a277f35f75e4fcb74279ab6ef203c1dc3b0 Mon Sep 17 00:00:00 2001 From: Aditya Gannavarapu Date: Mon, 14 Mar 2022 17:16:11 +0530 Subject: [PATCH 1/2] Change library to parse multiple servers --- index.js | 61 +++++++++++++++++++++++------------- openapi-to-har.js | 78 +++++++++++++++++++++++------------------------ test/test.js | 69 ++++++++++++++++++++--------------------- 3 files changed, 113 insertions(+), 95 deletions(-) diff --git a/index.js b/index.js index ea07bdf..06a45c3 100644 --- a/index.js +++ b/index.js @@ -30,8 +30,11 @@ const getEndpointSnippets = function (openApi, path, method, targets, values) { const hars = OpenAPIToHar.getEndpoint(openApi, path, method, values); - const snippets = []; + console.log(hars); + + let results = []; for (const har of hars) { + const snippets = []; const snippet = new HTTPSnippet(har); snippets.push( ...getSnippetsForTargets( @@ -40,17 +43,25 @@ const getEndpointSnippets = function (openApi, path, method, targets, values) { har.comment ? har.comment : undefined ) ); + + // check if multiple content types + let result = results.find((result) => result.url === har.url); + if (result) { + result.snippets.push(...snippets); + continue; + } + + // push for multiple servers + results.push({ + method: har.method, + url: har.url, + description: har.description, + resource: getResourceName(har.url), + snippets: snippets, + }); } - // use first element since method, url, and description - // are the same for all elements - return { - method: hars[0].method, - url: hars[0].url, - description: hars[0].description, - resource: getResourceName(hars[0].url), - snippets: snippets, - }; + return results; }; /** @@ -67,29 +78,35 @@ const getSnippets = function (openApi, targets) { for (let i in endpointHarInfoList) { // create HTTPSnippet object: const harInfo = endpointHarInfoList[i]; - const snippets = []; + // create a new harlist array for each endpoint + let harList = []; for (const har of harInfo.hars) { + const snippets = []; const snippet = new HTTPSnippet(har); snippets.push(...getSnippetsForTargets(targets, snippet, har.comment)); + harList.push({ + method: har.method, + url: har.url, + description: har.description, + resource: getResourceName(har.url), + snippets, + }); } - - results.push({ - method: harInfo.method, - url: harInfo.url, - description: harInfo.description, - resource: getResourceName(harInfo.url), - snippets, - }); + // push snippets of each har corresponding to different servers + results.push(harList); } // sort results: results.sort((a, b) => { - if (a.resource < b.resource) { + if (a[0].resource < b[0].resource) { return -1; - } else if (a.resource > b.resource) { + } else if (a[0].resource > b[0].resource) { return 1; } else { - return getMethodOrder(a.method.toLowerCase(), b.method.toLowerCase()); + return getMethodOrder( + a[0].method.toLowerCase(), + b[0].method.toLowerCase() + ); } }); diff --git a/openapi-to-har.js b/openapi-to-har.js index 5ca81c4..2800e0a 100644 --- a/openapi-to-har.js +++ b/openapi-to-har.js @@ -36,40 +36,42 @@ const createHar = function (openApi, path, method, queryParamValues) { queryParamValues = {}; } - const baseUrl = getBaseUrl(openApi, path, method); - - const baseHar = { - method: method.toUpperCase(), - url: baseUrl + getFullPath(openApi, path, method), - headers: getHeadersArray(openApi, path, method), - queryString: getQueryStrings(openApi, path, method, queryParamValues), - httpVersion: 'HTTP/1.1', - cookies: [], - headersSize: 0, - bodySize: 0, - }; + const baseUrls = getBaseUrl(openApi, path, method); let hars = []; - // get payload data, if available: - const postDatas = getPayloads(openApi, path, method); - - // For each postData create a snippet - if (postDatas.length > 0) { - for (let i in postDatas) { - const postData = postDatas[i]; - const copiedHar = JSON.parse(JSON.stringify(baseHar)); - copiedHar.postData = postData; - copiedHar.comment = postData.mimeType; - copiedHar.headers.push({ - name: 'content-type', - value: postData.mimeType, - }); - hars.push(copiedHar); + baseUrls.forEach((baseUrl) => { + const baseHar = { + method: method.toUpperCase(), + url: baseUrl + getFullPath(openApi, path, method), + headers: getHeadersArray(openApi, path, method), + queryString: getQueryStrings(openApi, path, method, queryParamValues), + httpVersion: 'HTTP/1.1', + cookies: [], + headersSize: 0, + bodySize: 0, + }; + + // get payload data, if available: + const postDatas = getPayloads(openApi, path, method); + + // For each postData create a snippet + if (postDatas.length > 0) { + for (let i in postDatas) { + const postData = postDatas[i]; + const copiedHar = JSON.parse(JSON.stringify(baseHar)); + copiedHar.postData = postData; + copiedHar.comment = postData.mimeType; + copiedHar.headers.push({ + name: 'content-type', + value: postData.mimeType, + }); + hars.push(copiedHar); + } + } else { + hars.push(baseHar); } - } else { - hars = [baseHar]; - } + }); return hars; }; @@ -193,9 +195,10 @@ const getPayloads = function (openApi, path, method) { */ const getBaseUrl = function (openApi, path, method) { if (openApi.paths[path][method].servers) - return openApi.paths[path][method].servers[0].url; - if (openApi.paths[path].servers) return openApi.paths[path].servers[0].url; - if (openApi.servers) return openApi.servers[0].url; + return openApi.paths[path][method].servers.map((server) => server.url); + if (openApi.paths[path].servers) + return openApi.paths[path].servers.map((server) => server.url); + if (openApi.servers) return openApi.servers.map((server) => server.url); let baseUrl = ''; if (typeof openApi.schemes !== 'undefined') { @@ -210,7 +213,7 @@ const getBaseUrl = function (openApi, path, method) { baseUrl += '://' + openApi.host + openApi.basePath; } - return baseUrl; + return [baseUrl]; }; /** @@ -503,14 +506,12 @@ const openApiToHarList = function (openApi) { try { // iterate openApi and create har objects: const harList = []; + for (let path in openApi.paths) { for (let method in openApi.paths[path]) { - const url = getBaseUrl(openApi, path, method) + path; const hars = createHar(openApi, path, method); - // need to push multiple here + // use hars from createHar for each server endpoint harList.push({ - method: method.toUpperCase(), - url: url, description: openApi.paths[path][method].description || 'No description available', @@ -518,7 +519,6 @@ const openApiToHarList = function (openApi) { }); } } - return harList; } catch (e) { console.log(e); diff --git a/test/test.js b/test/test.js index b25e519..154b680 100644 --- a/test/test.js +++ b/test/test.js @@ -67,8 +67,8 @@ test('Getting snippets for endpoint should contain body', function (t) { 'post', ['node_request'] ); - t.true(/body/.test(result.snippets[0].content)); - t.true(/subPage/.test(result.snippets[0].content)); + t.true(/body/.test(result[0].snippets[0].content)); + t.true(/subPage/.test(result[0].snippets[0].content)); }); test('Getting snippets from OpenAPI 3.0.x should work', function (t) { @@ -85,19 +85,19 @@ test('Getting snippets from OpenAPI 3.0.x should work', function (t) { test('Testing server overrides', function (t) { t.plan(12); - const result = OpenAPISnippets.getSnippets(PetStoreOpenAPI3, ['c_libcurl']); - t.equal(result[0].url, 'https://method-override.example.com/pets'); - t.match(result[0].snippets[0].content, /.*method-override.example.com.*/); - t.doesNotMatch(result[0].snippets[0].content, /.*petstore.swagger.io.*/); - t.equal(result[1].url, 'http://petstore.swagger.io/api/pets/{id}'); - t.match(result[1].snippets[0].content, /.*petstore.swagger.io.*/); - t.doesNotMatch(result[1].snippets[0].content, /.*example.com.*/); - t.equal(result[2].url, 'https://path-override.example.com/pets'); - t.match(result[2].snippets[0].content, /.*path-override.example.com.*/); - t.doesNotMatch(result[2].snippets[0].content, /.*petstore.swagger.io.*/); - t.equal(result[3].url, 'http://petstore.swagger.io/api/pets/{id}'); - t.match(result[3].snippets[0].content, /.*petstore.swagger.io.*/); - t.doesNotMatch(result[3].snippets[0].content, /.*example.com.*/); + let result = OpenAPISnippets.getSnippets(PetStoreOpenAPI3, ['c_libcurl']); + t.equal(result[0][0].url, 'https://method-override.example.com/pets'); + t.match(result[0][0].snippets[0].content, /.*method-override.example.com.*/); + t.doesNotMatch(result[0][0].snippets[0].content, /.*petstore.swagger.io.*/); + t.equal(result[1][0].url, 'http://petstore.swagger.io/api/pets/{id}'); + t.match(result[1][0].snippets[0].content, /.*petstore.swagger.io.*/); + t.doesNotMatch(result[1][0].snippets[0].content, /.*example.com.*/); + t.equal(result[2][0].url, 'https://path-override.example.com/pets'); + t.match(result[2][0].snippets[0].content, /.*path-override.example.com.*/); + t.doesNotMatch(result[2][0].snippets[0].content, /.*petstore.swagger.io.*/); + t.equal(result[3][0].url, 'http://petstore.swagger.io/api/pets/{id}'); + t.match(result[3][0].snippets[0].content, /.*petstore.swagger.io.*/); + t.doesNotMatch(result[3][0].snippets[0].content, /.*example.com.*/); }); test('Testing optionally provided parameter values', function (t) { @@ -113,8 +113,9 @@ test('Testing optionally provided parameter values', function (t) { 'not-a-query-param': 'foo', } ); - t.true(/5000/.test(result.snippets[0].content)); - t.false(/not-a-query-param/.test(result.snippets[0].content)); + console.log(result); + t.true(/5000/.test(result[0].snippets[0].content)); + t.false(/not-a-query-param/.test(result[0].snippets[0].content)); }); test('Testing the case when default is present but a value is provided, use the provided value', function (t) { @@ -129,8 +130,8 @@ test('Testing the case when default is present but a value is provided, use the filter: 'assigned', } ); - t.true(/assigned/.test(result.snippets[0].content)); - t.false(/all/.test(result.snippets[0].content)); // The default value of `filter` is `all` + t.true(/assigned/.test(result[0].snippets[0].content)); + t.false(/all/.test(result[0].snippets[0].content)); // The default value of `filter` is `all` }); test('Testing the case when default is present but no value is provided, use the default', function (t) { @@ -142,8 +143,8 @@ test('Testing the case when default is present but no value is provided, use the 'get', ['node_request'] ); - t.false(/assigned/.test(result.snippets[0].content)); - t.true(/all/.test(result.snippets[0].content)); // The default value of `filter` is `all` + t.false(/assigned/.test(result[0].snippets[0].content)); + t.true(/all/.test(result[0].snippets[0].content)); // The default value of `filter` is `all` }); test('Referenced query parameters should be resolved', function (t) { @@ -153,7 +154,7 @@ test('Referenced query parameters should be resolved', function (t) { 'get', ['node_request'] ); - const snippet = result.snippets[0].content; + const snippet = result[0].snippets[0].content; t.true(/apikey/.test(snippet)); t.true(/showSourceText/.test(snippet)); t.end(); @@ -166,7 +167,7 @@ test('Resolve samples from nested examples', function (t) { 'post', ['node_request'] ); - const snippet = result.snippets[0].content; + const snippet = result[0].snippets[0].content; t.true(/username.*John78\'/.test(snippet)); t.true(/email.*john.smith@example.com\'/.test(snippet)); t.true(/phone.*\+1\-202\-555\-0192/.test(snippet)); @@ -181,7 +182,7 @@ test('Parameters that are Schema References Are Dereferenced', function (t) { 'post', ['node_request'] ); - const snippet = result.snippets[0].content; + const snippet = result[0].snippets[0].content; t.true(/pet: 'SOME_OBJECT_VALUE'/.test(snippet)); t.end(); }); @@ -194,7 +195,7 @@ test('Testing the case when an example is provided, use the provided example val 'get', ['node_request'] ); - const snippet = result.snippets[0].content; + const snippet = result[0].snippets[0].content; t.true(/ {tags: 'dog,cat', limit: '10'}/.test(snippet)); t.false(/SOME_INTEGER_VALUE/.test(snippet)); t.end(); @@ -207,7 +208,7 @@ test('Generate snippet with multipart/form-data', function (t) { 'patch', ['node_request'] ); - const snippet = result.snippets[0].content; + const snippet = result[0].snippets[0].content; t.true(/boundary=---011000010111000001101001/.test(snippet)); t.true( /formData: {'pet\[name\]': 'string', 'pet\[tag\]': 'string'}/.test(snippet) @@ -222,7 +223,7 @@ test('Generate snippet with multipart/form-data with array', function (t) { 'patch', ['node_request'] ); - const snippet = result.snippets[0].content; + const snippet = result[0].snippets[0].content; t.true(/boundary=---011000010111000001101001/.test(snippet)); t.true(/formData: {'pet\[tags\]': '\["string"\]'}/.test(snippet)); t.end(); @@ -235,7 +236,7 @@ test('Generate snippet with multipart/form-data with object', function (t) { 'patch', ['node_request'] ); - const snippet = result.snippets[0].content; + const snippet = result[0].snippets[0].content; t.true(/boundary=---011000010111000001101001/.test(snippet)); t.true( /formData: {'pet\[feedingSchedule\]': '{"time":"string","food":"string"}'}/.test( @@ -252,8 +253,8 @@ test('Generate snippets with multiple content types', function (t) { 'patch', ['node_request'] ); - t.equal(result.snippets.length, 2); - for (const snippet of result.snippets) { + t.equal(result[0].snippets.length, 2); + for (const snippet of result[0].snippets) { if (snippet.mimeType === 'application/json') { t.true( /headers: {'content-type': 'application\/json'}/.test(snippet.content) @@ -282,7 +283,7 @@ test('Query Params Defined for all methods should be resolved', function (t) { 'get', ['node_request'] ); - const snippet = result.snippets[0].content; + const snippet = result[0].snippets[0].content; t.true(/ {tags: 'dog,cat', limit: '10'}/.test(snippet)); t.false(/SOME_INTEGER_VALUE/.test(snippet)); t.end(); @@ -295,7 +296,7 @@ test('Query Params Defined for all methods are overriden by method definitions', 'get', ['node_request'] ); - const snippet = result.snippets[0].content; + const snippet = result[0].snippets[0].content; t.true(/ qs: {id: '1,2'}/.test(snippet)); t.end(); }); @@ -307,7 +308,7 @@ test('Snippet for Get with no parameters should work', function (t) { 'get', ['node_request'] ); - const snippet = result.snippets[0].content; + const snippet = result[0].snippets[0].content; t.false(/qs/.test(snippet)); t.end(); }); @@ -320,7 +321,7 @@ test('Testing the application/x-www-form-urlencoded example case', function (t) 'post', ['shell_curl'] ); - const snippet = result.snippets[0].content; + const snippet = result[0].snippets[0].content; t.match(snippet, /.*--data 'id=id\+example\+value'.*/); t.match(snippet, /.*--data 'secret=secret\+example\+value'.*/); t.end(); From f842cded71ee010c69dfc1a2b96bf91d27bcfb2c Mon Sep 17 00:00:00 2001 From: Aditya Date: Mon, 14 Mar 2022 17:18:01 +0530 Subject: [PATCH 2/2] Remove console.log --- index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/index.js b/index.js index 06a45c3..ce2b5d5 100644 --- a/index.js +++ b/index.js @@ -30,8 +30,6 @@ const getEndpointSnippets = function (openApi, path, method, targets, values) { const hars = OpenAPIToHar.getEndpoint(openApi, path, method, values); - console.log(hars); - let results = []; for (const har of hars) { const snippets = [];