code-changes: add support for x-ms-parameterized-host

This commit is contained in:
Amar Zavery 2017-11-20 12:39:15 -08:00
Родитель 92f8d57c9c
Коммит c17fc72aff
5 изменённых файлов: 69 добавлений и 3 удалений

Просмотреть файл

@ -47,6 +47,12 @@ exports.builder = {
boolean: true,
default: false
},
t: {
alias: 'parameterizedHost',
describe: 'Should "x-ms-parameterized-host" extension be resolved?',
boolean: true,
default: false
},
d: {
alias: 'outputDir',
describe: 'Output directory where the resolved swagger spec will be stored.',
@ -65,12 +71,13 @@ exports.handler = function (argv) {
vOptions.shouldResolveXmsExamples = argv.e;
vOptions.shouldResolveAllOf = argv.o;
vOptions.shouldSetAdditionalPropertiesFalse = argv.a;
vOptions.shouldResolveParameterizedHost = argv.t;
vOptions.shouldResolvePureObjects = argv.p;
vOptions.shouldResolveDiscriminator = argv.c;
function execResolve() {
if (specPath.match(/.*composite.*/ig) !== null) {
return validate.validateCompositeSpec(specPath, argv.d, vOptions);
return validate.resolveCompositeSpec(specPath, argv.d, vOptions);
} else {
return validate.resolveSpec(specPath, argv.d, vOptions);
}

Просмотреть файл

@ -9,6 +9,7 @@ var Constants = {
exampleInSpec: 'example-in-spec',
BodyParameterValid: 'BODY_PARAMETER_VALID',
xmsSkipUrlEncoding: 'x-ms-skip-url-encoding',
xmsParameterizedHost: 'x-ms-parameterized-host',
Errors: 'Errors',
Warnings: 'Warnings',
ErrorCodes: {

Просмотреть файл

@ -61,6 +61,10 @@ exports.validateSpec = function validateSpec(specPath, options) {
// Hence we disable it since it is not required for semantic check.
options.shouldResolveDiscriminator = false;
// parameters in 'x-ms-parameterized-host' extension need not be resolved for semantic
// validation as that would not match the path parameters defined in the path template
// and cause the semantic validation to fail.
options.shouldResolveParameterizedHost = false;
let validator = new SpecValidator(specPath, null, options);
exports.finalValidationResult[specPath] = validator.specValidationResult;
return validator.initialize().then(function () {

Просмотреть файл

@ -42,6 +42,8 @@ class SpecResolver {
*
* @param {object} [options.shouldResolvePureObjects] Should pure objects be resolved? Default: true
*
* @param {object} [options.shouldResolveParameterizedHost] Should x-ms-parameterized-host be resolved? Default: true
*
* @return {object} An instance of the SpecResolver class.
*/
constructor(specPath, specInJson, options) {
@ -77,6 +79,10 @@ class SpecResolver {
options.shouldResolveDiscriminator = true;
}
if (options.shouldResolveParameterizedHost === null || options.shouldResolveParameterizedHost === undefined) {
options.shouldResolveParameterizedHost = true;
}
// Resolving allOf is a neccessary precondition for resolving discriminators. Hence hard setting this to true
if (options.shouldResolveDiscriminator) {
options.shouldResolveAllOf = true;
@ -140,6 +146,12 @@ class SpecResolver {
} else {
return Promise.resolve(self);
}
}).then(() => {
if (self.options.shouldResolveParameterizedHost) {
return self.resolveParameterizedHost();
} else {
return Promise.resolve(self);
}
}).then(() => {
if (self.options.shouldResolvePureObjects) {
return self.resolvePureObjects();
@ -443,6 +455,43 @@ class SpecResolver {
return Promise.resolve(self);
}
/**
* Resolves the parameters provided in 'x-ms-parameterized-host'
* extension by adding those parameters as local parameters to every operation.
*
* ModelValidation:
* This step should only be performed for model validation as we need to
* make sure that the examples contain correct values for parameters
* defined in 'x-ms-parameterized-host'.hostTemplate. Moreover, they are a
* part of the baseUrl.
*
* SemanticValidation:
* This step should not be performed for semantic validation, othwerise there will
* be a mismatch between the number of path parameters provided in the operation
* definition and the number pf parameters actually present in the path template.
*/
resolveParameterizedHost() {
let self = this;
let spec = self.specInJson;
let parameterizedHost = spec[Constants.xmsParameterizedHost];
let hostParameters = parameterizedHost ? parameterizedHost.parameters : null;
if (parameterizedHost && hostParameters) {
let paths = spec.paths;
for (let path in paths) {
let verbs = paths[path];
for (let verb in verbs) {
let operation = verbs[verb];
let operationParameters = operation.parameters;
if (!operationParameters) operationParameters = [];
// merge host parameters into parameters for that operation.
operation.parameters = operationParameters.concat(hostParameters);
}
}
}
return Promise.resolve(self);
}
/**
* Resolves entities (parameters, definitions, model properties, etc.) in the spec that are true ojects.
* i.e `"type": "object"` and `"properties": {}` or `"properties"` is absent or the entity has

Просмотреть файл

@ -44,6 +44,8 @@ class SpecValidator {
*
* @param {object} [options.shouldResolvePureObjects] Should pure objects be resolved? Default: true
*
* @param {object} [options.shouldResolveParameterizedHost] Should 'x-ms-parameterized-host' be resolved? Default: true
*
* @return {object} An instance of the SpecValidator class.
*/
constructor(specPath, specInJson, options) {
@ -569,10 +571,13 @@ class SpecValidator {
let result = { request: null, validationResult: { errors: [], warnings: [] } }, foundIssues = false;
let options = {};
let formDataFiles = null;
if (operation.pathObject && operation.pathObject.api && operation.pathObject.api.host) {
let parameterizedHost = operation.pathObject.api[Constants.xmsParameterizedHost];
let hostTemplate = parameterizedHost && parameterizedHost.hostTemplate ? parameterizedHost.hostTemplate : null;
if (operation.pathObject && operation.pathObject.api && (operation.pathObject.api.host || hostTemplate)) {
let scheme = 'https';
let basePath = '';
let host = operation.pathObject.api.host;
let host = '';
host = operation.pathObject.api.host || hostTemplate;
if (host.endsWith('/'))
host = host.slice(0, host.length - 1);
if (operation.pathObject.api.schemes && !operation.pathObject.api.schemes.some((item) => { return item && item.toLowerCase() === 'https'; }))