Skip to content

Commit d45c9ab

Browse files
authored
fix(execute): handle Server Objects overrides for OpenAPI 2.0/3.0.x (#3221)
This change is specific to OpenAPI 2.0 and OpenAPI 3.0.x. Refs #2967
1 parent 4682656 commit d45c9ab

File tree

3 files changed

+40
-27
lines changed

3 files changed

+40
-27
lines changed

src/constants.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
export const ACCEPT_HEADER_VALUE_FOR_DOCUMENTS = 'application/json, application/yaml';
22

33
export const DEFAULT_BASE_URL = 'https://swagger.io';
4+
5+
export const DEFAULT_OPENAPI_3_SERVER = Object.freeze({ url: '/' });

src/execute/index.js

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import cookie from 'cookie';
22
import { isPlainObject } from 'is-plain-object';
33
import { url } from '@swagger-api/apidom-reference/configuration/empty';
44

5-
import { DEFAULT_BASE_URL } from '../constants.js';
5+
import { DEFAULT_BASE_URL, DEFAULT_OPENAPI_3_SERVER } from '../constants.js';
66
import stockHttp, { mergeInQueryOrForm } from '../http/index.js';
77
import createError from '../specmap/lib/create-error.js';
88
import SWAGGER2_PARAMETER_BUILDERS from './swagger2/parameter-builders.js';
@@ -319,40 +319,47 @@ export function baseUrl(obj) {
319319
return specIsOAS3 ? oas3BaseUrl(obj) : swagger2BaseUrl(obj);
320320
}
321321

322-
function oas3BaseUrl({ spec, pathName, method, server, contextUrl, serverVariables = {} }) {
323-
const servers =
324-
spec?.paths?.[pathName]?.[(method || '').toLowerCase()]?.servers ||
325-
spec?.paths?.[pathName]?.servers ||
326-
spec?.servers;
322+
const isNonEmptyServerList = (value) => Array.isArray(value) && value.length > 0;
327323

324+
function oas3BaseUrl({ spec, pathName, method, server, contextUrl, serverVariables = {} }) {
325+
let servers = [];
328326
let selectedServerUrl = '';
329-
let selectedServerObj = null;
330-
331-
if (server && servers && servers.length) {
332-
const serverUrls = servers.map((srv) => srv.url);
333-
334-
if (serverUrls.indexOf(server) > -1) {
335-
selectedServerUrl = server;
336-
selectedServerObj = servers[serverUrls.indexOf(server)];
337-
}
327+
let selectedServerObj;
328+
329+
// compute the servers (this will be taken care of by ApiDOM refrator plugins in future
330+
const operationLevelServers = spec?.paths?.[pathName]?.[(method || '').toLowerCase()]?.servers;
331+
const pathItemLevelServers = spec?.paths?.[pathName]?.servers;
332+
const rootLevelServers = spec?.servers;
333+
servers = isNonEmptyServerList(operationLevelServers) // eslint-disable-line no-nested-ternary
334+
? operationLevelServers
335+
: isNonEmptyServerList(pathItemLevelServers) // eslint-disable-line no-nested-ternary
336+
? pathItemLevelServers
337+
: isNonEmptyServerList(rootLevelServers)
338+
? rootLevelServers
339+
: [DEFAULT_OPENAPI_3_SERVER];
340+
341+
// pick the first server that matches the server url
342+
if (server) {
343+
selectedServerObj = servers.find((srv) => srv.url === server);
344+
if (selectedServerObj) selectedServerUrl = server;
338345
}
339346

340-
if (!selectedServerUrl && servers && servers.length) {
341-
// default to the first server if we don't have one by now
342-
selectedServerUrl = servers[0].url; // eslint-disable-line semi
343-
[selectedServerObj] = servers;
347+
// default to the first server if we don't have one by now
348+
if (!selectedServerUrl) {
349+
selectedServerObj = servers.at(0);
350+
selectedServerUrl = selectedServerObj.url;
344351
}
345352

346353
if (selectedServerUrl.includes('{')) {
347354
// do variable substitution
348355
const varNames = getVariableTemplateNames(selectedServerUrl);
349-
varNames.forEach((vari) => {
350-
if (selectedServerObj.variables && selectedServerObj.variables[vari]) {
356+
varNames.forEach((variable) => {
357+
if (selectedServerObj.variables && selectedServerObj.variables[variable]) {
351358
// variable is defined in server
352-
const variableDefinition = selectedServerObj.variables[vari];
353-
const variableValue = serverVariables[vari] || variableDefinition.default;
359+
const variableDefinition = selectedServerObj.variables[variable];
360+
const variableValue = serverVariables[variable] || variableDefinition.default;
354361

355-
const re = new RegExp(`{${vari}}`, 'g');
362+
const re = new RegExp(`{${variable}}`, 'g');
356363
selectedServerUrl = selectedServerUrl.replace(re, variableValue);
357364
}
358365
});
@@ -378,7 +385,7 @@ function buildOas3UrlWithContext(ourUrl = '', contextUrl = '') {
378385
if (computedScheme && computedHost) {
379386
res = `${computedScheme}://${computedHost + computedPath}`;
380387

381-
// If last character is '/', trim it off
388+
// if last character is '/', trim it off
382389
} else {
383390
res = computedPath;
384391
}

src/index.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* eslint-disable camelcase */
2+
import { DEFAULT_OPENAPI_3_SERVER } from './constants.js';
23
import Http, { makeHttp, serializeRes, serializeHeaders } from './http/index.js';
34
import { makeResolve } from './resolver/index.js';
45
import { makeResolveSubtree } from './subtree-resolver/index.js';
@@ -135,6 +136,7 @@ Swagger.prototype.applyDefaults = function applyDefaults() {
135136

136137
if (isOpenAPI2(spec) && isHttpUrl(specUrl)) {
137138
const parsed = new URL(specUrl);
139+
138140
if (!spec.host) {
139141
spec.host = parsed.host;
140142
}
@@ -145,8 +147,10 @@ Swagger.prototype.applyDefaults = function applyDefaults() {
145147
spec.basePath = '/';
146148
}
147149
} else if (isOpenAPI3(spec)) {
148-
if (!spec.servers || (Array.isArray(spec.servers) && spec.servers.length === 0)) {
149-
spec.servers = [{ url: '/' }];
150+
const isEmptyServerList = Array.isArray(spec.servers) && spec.servers.length === 0;
151+
152+
if (!spec.servers || isEmptyServerList) {
153+
spec.servers = [DEFAULT_OPENAPI_3_SERVER];
150154
}
151155
}
152156
};

0 commit comments

Comments
 (0)