Changeset View
Changeset View
Standalone View
Standalone View
swh/web/api/apiurls.py
Show All 15 Lines | |||||
from swh.web.utils.urlsindex import UrlsIndex | from swh.web.utils.urlsindex import UrlsIndex | ||||
CategoryId = Literal[ | CategoryId = Literal[ | ||||
"Archive", "Batch download", "Metadata", "Request archival", "Miscellaneous", "test" | "Archive", "Batch download", "Metadata", "Request archival", "Miscellaneous", "test" | ||||
] | ] | ||||
class APIUrls(UrlsIndex): | class APIUrls(UrlsIndex): | ||||
""" | """Class to manage API URLs and endpoint documentation URLs.""" | ||||
Class to manage API documentation URLs. | |||||
- Indexes all routes documented using apidoc's decorators. | |||||
- Tracks endpoint/request processing method relationships for use in | |||||
generating related urls in API documentation | |||||
""" | |||||
_apidoc_routes: Dict[str, Dict[str, str]] = {} | apidoc_routes: Dict[str, Dict[str, str]] = {} | ||||
scope = "api" | |||||
@classmethod | def get_app_endpoints(self) -> Dict[str, Dict[str, str]]: | ||||
def get_app_endpoints(cls) -> Dict[str, Dict[str, str]]: | return self.apidoc_routes | ||||
return cls._apidoc_routes | |||||
@classmethod | |||||
def add_doc_route( | def add_doc_route( | ||||
cls, | self, | ||||
route: str, | route: str, | ||||
category: CategoryId, | category: CategoryId, | ||||
docstring: str, | docstring: str, | ||||
noargs: bool = False, | noargs: bool = False, | ||||
api_version: str = "1", | api_version: str = "1", | ||||
**kwargs, | **kwargs, | ||||
) -> None: | ) -> None: | ||||
""" | """ | ||||
Add a route to the self-documenting API reference | Add a route to the self-documenting API reference | ||||
""" | """ | ||||
route_name = route[1:-1].replace("/", "-") | route_name = route[1:-1].replace("/", "-") | ||||
if not noargs: | if not noargs: | ||||
route_name = "%s-doc" % route_name | route_name = "%s-doc" % route_name | ||||
route_view_name = "api-%s-%s" % (api_version, route_name) | route_view_name = "api-%s-%s" % (api_version, route_name) | ||||
if route not in cls._apidoc_routes: | if route not in self.apidoc_routes: | ||||
d = { | d = { | ||||
"category": category, | "category": category, | ||||
"docstring": docstring, | "docstring": docstring, | ||||
"route": "/api/%s%s" % (api_version, route), | "route": "/api/%s%s" % (api_version, route), | ||||
"route_view_name": route_view_name, | "route_view_name": route_view_name, | ||||
} | } | ||||
for k, v in kwargs.items(): | for k, v in kwargs.items(): | ||||
d[k] = v | d[k] = v | ||||
cls._apidoc_routes[route] = d | self.apidoc_routes[route] = d | ||||
api_urls = APIUrls() | |||||
def api_route( | def api_route( | ||||
url_pattern: str, | url_pattern: str, | ||||
view_name: str, | view_name: str, | ||||
methods: List[str] = ["GET", "HEAD", "OPTIONS"], | methods: List[str] = ["GET", "HEAD", "OPTIONS"], | ||||
throttle_scope: str = "swh_api", | throttle_scope: str = "swh_api", | ||||
api_version: str = "1", | api_version: str = "1", | ||||
checksum_args: Optional[List[str]] = None, | checksum_args: Optional[List[str]] = None, | ||||
never_cache: bool = False, | never_cache: bool = False, | ||||
api_urls: APIUrls = api_urls, | |||||
): | ): | ||||
""" | """ | ||||
Decorator to ease the registration of an API endpoint | Decorator to ease the registration of an API endpoint | ||||
using the Django REST Framework. | using the Django REST Framework. | ||||
Args: | Args: | ||||
url_pattern: the url pattern used by DRF to identify the API route | url_pattern: the url pattern used by DRF to identify the API route | ||||
view_name: the name of the API view associated to the route used to | view_name: the name of the API view associated to the route used to | ||||
Show All 32 Lines | def decorator(f): | ||||
return api_response | return api_response | ||||
# small hacks for correctly generating API endpoints index doc | # small hacks for correctly generating API endpoints index doc | ||||
api_view_f.__name__ = f.__name__ | api_view_f.__name__ = f.__name__ | ||||
api_view_f.http_method_names = methods | api_view_f.http_method_names = methods | ||||
# register the route and its view in the endpoints index | # register the route and its view in the endpoints index | ||||
APIUrls.add_url_pattern(url_pattern, api_view_f, view_name) | api_urls.add_url_pattern(url_pattern, api_view_f, view_name) | ||||
if checksum_args: | if checksum_args: | ||||
APIUrls.add_redirect_for_checksum_args( | api_urls.add_redirect_for_checksum_args( | ||||
view_name, [url_pattern], checksum_args | view_name, [url_pattern], checksum_args | ||||
) | ) | ||||
return f | return f | ||||
return decorator | return decorator |