diff --git a/flask_apispec/extension.py b/flask_apispec/extension.py index 68636b1..b46b039 100644 --- a/flask_apispec/extension.py +++ b/flask_apispec/extension.py @@ -36,14 +36,17 @@ def get_pet(pet_id): :param Flask app: App associated with API documentation :param APISpec spec: apispec specification associated with API documentation + :param bool support_multiple_version: support multiple version swaggers + by register doc to 'swagger-{api_version}' url """ - def __init__(self, app=None): + def __init__(self, app=None, support_multiple_version=False): self._deferred = [] self.app = app self.view_converter = None self.resource_converter = None self.spec = None + self.support_multiple_version = support_multiple_version if app: self.init_app(app) @@ -67,9 +70,13 @@ def _defer(self, callable, *args, **kwargs): if self.app: bound() + @property + def blueprint_name(self): + return 'flask-apispec-' + self.spec.version if self.support_multiple_version else 'flask-apispec' + def add_swagger_routes(self): blueprint = flask.Blueprint( - 'flask-apispec', + self.blueprint_name, __name__, static_folder='./static', template_folder='./templates', @@ -78,19 +85,37 @@ def add_swagger_routes(self): json_url = self.app.config.get('APISPEC_SWAGGER_URL', '/swagger/') if json_url: + if self.support_multiple_version: + json_url = self.make_url_with_suffix_version(json_url) + blueprint.add_url_rule(json_url, 'swagger-json', self.swagger_json) ui_url = self.app.config.get('APISPEC_SWAGGER_UI_URL', '/swagger-ui/') if ui_url: + if self.support_multiple_version: + ui_url = self.make_url_with_suffix_version(ui_url) blueprint.add_url_rule(ui_url, 'swagger-ui', self.swagger_ui) self.app.register_blueprint(blueprint) + def make_url_with_suffix_version(self, url): + # adding version suffix + if url.endswith('/'): + url = url[:-1] + '-' + self.spec.version + '/' + elif url.endswith('.json') or url.endswith('.html'): + # support extension url + url = url.replace('.json', '-' + self.spec.version + '.json') \ + .replace('.html', '-' + self.spec.version + '.html') + else: + url += '-' + self.spec.version + return url + def swagger_json(self): return flask.jsonify(self.spec.to_dict()) def swagger_ui(self): - return flask.render_template('swagger-ui.html') + return flask.render_template('swagger-ui.html', + blueprint_name=self.blueprint_name) def register_existing_resources(self): for name, rule in self.app.view_functions.items(): diff --git a/flask_apispec/templates/swagger-ui.html b/flask_apispec/templates/swagger-ui.html index 3752e62..7a89942 100644 --- a/flask_apispec/templates/swagger-ui.html +++ b/flask_apispec/templates/swagger-ui.html @@ -3,19 +3,19 @@ Swagger UI - - - + + +
 
- - + + diff --git a/tests/test_extension.py b/tests/test_extension.py index f1f5a7a..2243cc9 100644 --- a/tests/test_extension.py +++ b/tests/test_extension.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +import random import pytest from flask import Blueprint @@ -98,3 +99,29 @@ def test_apispec_config(self, app): assert docs.spec.title == 'test-extension' assert docs.spec.version == '2.1' assert docs.spec.openapi_version == '2.0' + + def test_make_url_with_suffix_version_with_version(self, app): + app.config['APISPEC_VERSION'] = 'v2' + docs = FlaskApiSpec(app, support_multiple_version=True) + + assert docs.make_url_with_suffix_version('/swagger/') == '/swagger-v2/' + assert docs.make_url_with_suffix_version('/swagger-ui/') == '/swagger-ui-v2/' + assert docs.make_url_with_suffix_version('/swagger.json') == '/swagger-v2.json' + assert docs.make_url_with_suffix_version('/swagger.html') == '/swagger-v2.html' + assert docs.make_url_with_suffix_version('/swagger') == '/swagger-v2' + + def test_urls_with_support_multiple_version(self, app, client): + app.config['APISPEC_VERSION'] = 'v2' + docs = FlaskApiSpec(app, support_multiple_version=True) + res = client.get('/swagger-v2/') + assert res.json == docs.spec.to_dict() + client.get('/swagger-ui-v2/') + + def test_support_multiple_version_by_changing_blueprint_name(self, app): + version = 'v{}'.format(random.randint(1, 5)) + app.config['APISPEC_VERSION'] = version + docs = FlaskApiSpec(app, support_multiple_version=True) + assert docs.blueprint_name == 'flask-apispec-' + version + + docs_without_support_multiple_version = FlaskApiSpec(app) + assert docs_without_support_multiple_version.blueprint_name == 'flask-apispec'