Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/expose only supported methods #35

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
56 changes: 32 additions & 24 deletions falcon_apispec/falcon_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import re
from apispec import BasePlugin, yaml_utils
from apispec.exceptions import APISpecError

from apispec.core import VALID_METHODS
from falcon.routing import map_http_methods

class FalconPlugin(BasePlugin):
"""APISpec plugin for Falcon"""
Expand All @@ -11,45 +12,52 @@ 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)
def init_spec(self, spec):
self._spec = spec

def _get_valid_methods(self):
return set(VALID_METHODS[self._spec.openapi_version.major])

mapping = {}
for route in routes_to_check:
uri = route.uri_template
resource = route.resource
mapping[resource] = {
"uri": uri,
"methods": {}
}
def _generate_resource_uri(self, resource):
valid_methods = self._get_valid_methods()
routes_to_check = copy.copy(self._app._router._roots)

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]["methods"][method_name.lower()] = method_handler
route = next(filter(lambda r: r.resource == resource, routes_to_check), None)
resource_methods = map_http_methods(resource)

routes_to_check.extend(route.children)
return mapping
uri = route.uri_template
methods = {}
if resource_methods:
for method_name, method_handler in resource_methods.items():
if method_handler.__module__ == "falcon.responders":
continue
if method_name.lower() not in valid_methods:
continue
if method_name.lower() not in valid_methods:
continue
methods[method_name.lower()] = method_handler

return {
"uri": uri,
"methods": methods
}

def path_helper(self, 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:
resource_uri = self._generate_resource_uri(resource)
if not resource_uri:
raise APISpecError("Could not find endpoint for resource {0}".format(resource))

operations.update(yaml_utils.load_operations_from_docstring(resource.__doc__) or {})
path = resource_uri_mapping[resource]["uri"]
path = resource_uri["uri"]

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]["methods"]
methods = resource_uri["methods"]

for method_name, method_handler in methods.items():
docstring_yaml = yaml_utils.load_yaml_from_docstring(method_handler.__doc__)
Expand Down
2 changes: 1 addition & 1 deletion falcon_apispec/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.4.0"
__version__ = "0.4.1"