Add support for suffix="collection" routes (Ref #18)
Closed this issue · 1 comments
Matt-Murungi commented
@hharutyunyan the issue now is that only one path per resource is mapped. All paths should be mapped for a given resource since that's why suffixes were added to Falcon in the first place.
I'm thinking calls to spec.path
for multiple paths should look like:
spec.path('/accounts', resource=accounts)
spec.path('/accounts/{account_id}', resource=accounts)
And the plugin should be more like:
class FalconPlugin(BasePlugin):
"""APISpec plugin for Falcon"""
def __init__(self, app):
super(FalconPlugin, self).__init__()
self._app = app
@staticmethod
def _generate_resource_uri_mapping(app):
routes_to_check = copy.copy(app._router._roots)
mapping = {}
for route in routes_to_check:
uri = route.uri_template
resource = route.resource
if resource not in mapping:
mapping[resource] = {}
if uri not in mapping[resource]:
mapping[resource][uri] = {}
if route.method_map:
for method_name, method_handler in route.method_map.items():
if method_handler.__dict__.get("__module__") == "falcon.responders":
continue
mapping[resource][uri][method_name.lower()] = method_handler
routes_to_check.extend(route.children)
return mapping
def path_helper(self, path, operations, resource, base_path=None, **kwargs):
"""Path helper that allows passing a Falcon resource instance."""
resource_uri_mapping = self._generate_resource_uri_mapping(self._app)
if resource not in resource_uri_mapping:
raise APISpecError("Could not find endpoint for resource {0}".format(resource))
if path not in resource_uri_mapping[resource]:
raise APISpecError("Could not find path {0} for resource {1}".format(path, resource))
operations.update(yaml_utils.load_operations_from_docstring(resource.__doc__) or {})
if base_path is not None:
# make sure base_path accept either with or without leading slash
# swagger 2 usually come with leading slash but not in openapi 3.x.x
base_path = '/' + base_path.strip('/')
path = re.sub(base_path, "", path, 1)
methods = resource_uri_mapping[resource][path]
for method_name, method_handler in methods.items():
docstring_yaml = yaml_utils.load_yaml_from_docstring(method_handler.__doc__)
operations[method_name] = docstring_yaml or dict()
return path
Originally posted by @chretienmn in #18 (comment)
Sylphe88 commented
APISpec does not support mapping a path to multiple methods of the same type (e.g. 2 GETs), and falcon-apispec binds a resource to a path at registration, so supporting this may prove to be much more challenging than it looks.
We could pass an additional kwarg to spec.path(resource=...) to specify we'd like to register the suffix'ed method(s)?