diff --git a/flask_restplus/swagger.py b/flask_restplus/swagger.py index b5a89b58..6a94ea81 100644 --- a/flask_restplus/swagger.py +++ b/flask_restplus/swagger.py @@ -258,7 +258,15 @@ def extract_resource_doc(self, resource, url, route_doc=None): doc = merge(getattr(resource, '__apidoc__', {}), route_doc) if doc is False: return False - doc['name'] = resource.__name__ + + # ensure unique names for multiple routes to the same resource + # provides different Swagger operationId's + doc["name"] = ( + "{}_{}".format(resource.__name__, url) + if route_doc + else resource.__name__ + ) + params = merge(self.expected_params(doc), doc.get('params', OrderedDict())) params = merge(params, extract_path_params(url)) # Track parameters for late deduplication diff --git a/tests/test_swagger.py b/tests/test_swagger.py index 9bbb7cc6..859994ae 100644 --- a/tests/test_swagger.py +++ b/tests/test_swagger.py @@ -3096,7 +3096,42 @@ def get(self): path = data['paths']['/bar'] assert path['get']['description'] == 'an endpoint' - def test_routes_merge_doc(self, api, client): + def test_multiple_routes_no_doc_same_operationIds(self, api, client): + @api.route('/foo/bar') + @api.route('/bar') + class TestResource(restplus.Resource): + def get(self): + pass + + data = client.get_specs() + + expected_operation_id = 'get_test_resource' + + path = data['paths']['/foo/bar'] + assert path['get']['operationId'] == expected_operation_id + + path = data['paths']['/bar'] + assert path['get']['operationId'] == expected_operation_id + + def test_multiple_routes_with_doc_unique_operationIds(self, api, client): + @api.route( + "/foo/bar", + doc={"description": "I should be treated separately"}, + ) + @api.route("/bar") + class TestResource(restplus.Resource): + def get(self): + pass + + data = client.get_specs() + + path = data['paths']['/foo/bar'] + assert path['get']['operationId'] == 'get_test_resource_/foo/bar' + + path = data['paths']['/bar'] + assert path['get']['operationId'] == 'get_test_resource' + + def test_mutltiple_routes_merge_doc(self, api, client): @api.route('/foo/bar', doc={'description': 'the same endpoint'}) @api.route('/bar', doc={'description': False}) @api.doc(security=[{'oauth2': ['read', 'write']}])