feat: simple variable substitution support

fixes #565
This commit is contained in:
Roman Hotsiy 2018-07-23 12:00:29 +03:00
parent 59e05fbe75
commit 9d6b30c55a
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0
3 changed files with 88 additions and 7 deletions

View File

@ -234,6 +234,24 @@ describe('Utils', () => {
expect(res).toEqual([{ url: 'http://base.com/sandbox/test', description: '' }]);
});
it('should correcly resolve url with server relative path', () => {
const res = normalizeServers('http://base.com/subpath/spec.yaml', [
{
url: '/sandbox/test',
},
]);
expect(res).toEqual([{ url: 'http://base.com/sandbox/test', description: '' }]);
});
it('should correcly resolve url with relative path', () => {
const res = normalizeServers('http://base.com/subpath/spec.yaml', [
{
url: 'sandbox/test',
},
]);
expect(res).toEqual([{ url: 'http://base.com/subpath/sandbox/test', description: '' }]);
});
it('should prefer server host over spec`s one', () => {
const res = normalizeServers('http://base.com/spec.yaml', [
{
@ -261,5 +279,35 @@ describe('Utils', () => {
]);
expect(res).toEqual([{ url: 'https://base.com/sandbox/test', description: 'test' }]);
});
it('should expand variables', () => {
const servers = normalizeServers('', [
{
url: '{protocol}{host}{basePath}',
variables: {
protocol: {
default: 'http://',
},
host: {
default: '127.0.0.1',
},
basePath: {
default: '/path/to/endpoint',
},
},
},
{
url: 'http://127.0.0.2:{port}',
variables: {},
},
{
url: 'http://127.0.0.3',
},
]);
expect(servers[0].url).toEqual('http://127.0.0.1/path/to/endpoint');
expect(servers[1].url).toEqual('http://127.0.0.2:{port}');
expect(servers[2].url).toEqual('http://127.0.0.3');
});
});
});

View File

@ -1,4 +1,5 @@
import slugify from 'slugify';
import { format, parse } from 'url';
/**
* Maps over array passing `isLast` bool to iterator as the second arguemnt
@ -133,3 +134,30 @@ export function safeSlugify(value: string): string {
.replace(/-+$/, '')
); // Trim - from end of text
}
export function isAbsoluteUrl(url: string) {
return /(?:^[a-z][a-z0-9+.-]*:|\/\/)/i.test(url);
}
/**
* simple resolve URL which doesn't break on strings with url fragments
* e.g. resolveUrl('http://test.com:{port}', 'path') results in http://test.com:{port}/path
*/
export function resolveUrl(url: string, to: string) {
let res;
if (to.startsWith('//')) {
const { protocol: specProtocol } = parse(url);
res = `${specProtocol}${to}`;
} else if (isAbsoluteUrl(to)) {
res = to;
} else if (!to.startsWith('/')) {
res = stripTrailingSlash(url) + '/' + to;
} else {
const urlObj = parse(url);
res = format({
...urlObj,
pathname: to,
});
}
return stripTrailingSlash(res);
}

View File

@ -1,5 +1,4 @@
import { dirname } from 'path';
import { parse as urlParse, resolve as resolveUrl } from 'url';
import { OpenAPIParser } from '../services/OpenAPIParser';
import {
@ -11,7 +10,7 @@ import {
Referenced,
} from '../types';
import { IS_BROWSER } from './dom';
import { isNumeric, stripTrailingSlash } from './helpers';
import { isNumeric, resolveUrl } from './helpers';
function isWildcardStatusCode(statusCode: string | number): statusCode is string {
return typeof statusCode === 'string' && /\dxx/i.test(statusCode);
@ -240,6 +239,13 @@ export function mergeSimilarMediaTypes(types: Dict<OpenAPIMediaType>): Dict<Open
return mergedTypes;
}
function expandVariables(url: string, variables: object = {}) {
return url.replace(
/(?:{)(\w+)(?:})/g,
(match, name) => (variables[name] && variables[name].default) || match,
);
}
export function normalizeServers(
specUrl: string | undefined,
servers: OpenAPIServer[],
@ -254,17 +260,16 @@ export function normalizeServers(
},
];
}
const { protocol: specProtocol } = urlParse(baseUrl);
function normalizeUrl(url: string): string {
url = resolveUrl(baseUrl, url);
return stripTrailingSlash(url.startsWith('//') ? `${specProtocol}${url}` : url);
function normalizeUrl(url: string, variables: object | undefined): string {
url = expandVariables(url, variables);
return resolveUrl(baseUrl, url);
}
return servers.map(server => {
return {
...server,
url: normalizeUrl(server.url),
url: normalizeUrl(server.url, server.variables),
description: server.description || '',
};
});